相邻两数的最大差值

11 篇文章 1 订阅
3 篇文章 1 订阅

给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度O(N),且要求不能用非基于比较的排序。

在这里插入图片描述

解题

1.已知数组长度为 N
2.遍历数组,找到整个数组中元素的最大值 max 和最小值 min
3.最小值放入0号桶,最大值放入N+1号桶
根据找到的 max 和 min,将数组均匀划分为 n + 1 个范围。
4.遍历数组,根据每个数组元素的值,判断需要进入哪个桶,最后找到每个桶中的最大值和最小值。
5.遍历数组 用该数组的最小值-前一个非空桶的最大值,更新全局Max(最大差值)
设立N+1个桶的目的 是因为必定会有一个空桶,那么最大差值就不会出席现在一个桶中 而且空桶前后不一定是最大差值

#include <iostream>
#include <cstring>
using namespace std;

const int N = 100010;

bool IsVisit[N+1];//判断一个桶是不是空桶 
int MinNum[N+1];//记录一个桶的最小值 
int MaxNum[N+1];//记录一个桶的最大值
int Arr[N];//原数组 

int FindPos(int nNum, int nMin, int nMax, int nLen);
//返回一个数 应该放入哪个桶
void PutInBucket(int nLen, int nMax, int nMin);//把所有的数放入桶里 
int GetMax(int nLen);//返回最大的差值 

int main(int argc, char** argv) 
{
	int nMin = 0x3f3f3f3f;
	int nMax = -2e9;
	
	memset(MaxNum,-2e9,sizeof(MaxNum));
	memset(MinNum,0x3f3f3f3f,sizeof(MinNum));
	
	//输入这个数组的长度 
	int nLen;
	scanf("%d",&nLen);
	
	//数组的赋值 并且求出这个数组的最大值和最小值 
	for(int i = 0; i < nLen; i++)
	{
		scanf("%d",&Arr[i]);
		nMin = min(nMin,Arr[i]);
		nMax = max(nMax,Arr[i]);
	}
	
	//数组中元素的值相等 最大差值0 
	if(nMin == nMax)
	{
		return 0;	
	} 
	
	PutInBucket(nLen, nMax, nMin);
	
	cout<<GetMax(nLen)<<endl;; 
	
	return 0;
}

int FindPos(long nNum, long nMin, long nMax, long nLen)
{
	return (int) (nNum-nMin) * nLen / (nMax-nMin);
}

void PutInBucket(int nLen, int nMax, int nMin)
{
	for(int i = 0; i < nLen; i++)
	{
		int nNum = Arr[i];
		int nPos = 
		FindPos((long)nNum, (long)nMin, (long)nMax, (long)nLen);
		
		//如果这个桶没有被访问过 
		if(!IsVisit[nPos])
		{
			MaxNum[nPos] = nNum; MinNum[nPos] = nNum; 
			IsVisit[nPos] = true;	
		}
		else
		{
			MaxNum[nPos] = 
			nNum > MaxNum[nPos] ? nNum : MaxNum[nPos];
			MinNum[nPos] = 
			nNum < MinNum[nPos] ? nNum : MinNum[nPos]; 
		}
	}
}

int GetMax(int nLen)
{
	int nRes = 0;//记录最大差值 
	int nLastMaxPos = 0;//记录上一个非空桶的位置 
	
	//注意此处 是遍历N+1个桶 
	for(int i = 0; i <= nLen; i++)
	{
		//这个桶不是空桶 
		if(IsVisit[i])
		{
			nRes = max(nRes, MinNum[i] - MaxNum[nLastMaxPos]);
			nLastMaxPos = i;
		}
	}
	
	return nRes;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值