每日一题(61) - 找出左边比它小,右边比它大的数

题目来自网络

题目:

给出一个元素无序的数组,求出一个数,使得其左边的数都小于它,右边的数都大于等于它。

举例:1,2,3,1,2,0,5,6,返回下标6(数字为5)。

思路(1):

朴素算法,对于每一个数,都检测它的左边和右边是否满足题意。

时间复杂度为O(n^2)

思路(2)

使用变量求解:

(1)目前找到符合题意的候选值,nCandid

(2)目前已遍历数组的最大值,nMax:为了选下一次的候选值

(3)目前的候选值是否有效,bIsExist:检测是否需要重新选择候选值

思路:如果候选值有效,可以继续遍历下面的数据

如果候选值小于目前的值,则该候选失效。之后遍历元素时,就要重新选择候选值

选择候选值时,对于某一个元素,如果该元素比之前遍历过元素的最大值还要大nMax,则该元素就为候选。

复杂度:遍历一遍数组即可,时间:O(n),空间O(1)

代码

#include <iostream>
#include <assert.h>
#include <list>
using namespace std;

int FindNum(int nArr[],int nLen)
{
	assert(nArr && nLen > 0);
	int nPos = 0;
	int nCandid = nArr[0];
	int nMax = nArr[0];
	bool bIsExist = true;
	for (int i = 1;i < nLen;i++)
	{
		if (bIsExist)//候选有效
		{
			if (nCandid > nArr[i])//候选失效
			{
				bIsExist = false;
			}
			else
			{
				nMax = nArr[i];
			}
		}
		else //候选失效
		{
			if (nArr[i] >= nMax)//重新找到候选
			{
				bIsExist = true;

				nCandid = nArr[i];
				nMax = nArr[i];	
				nPos = i;
			}
		}
	}
	return bIsExist ? nPos : -1; 
}

int main()
{
 	int nArr[8] = {1,2,3,1,2,0,5,6};
 	int nPos = FindNum(nArr,8);
 	if (nPos == -1)
 	{
 		cout<<"不存在!"<<endl;
 	}
 	else
 	{
 		cout<<nArr[nPos]<<endl;
 	}


// 	int nArr[7] = {7,7,7,7,7,7,7};
// 	int nPos = FindNum(nArr,7);
// 	if (nPos == -1)
// 	{
// 		cout<<"不存在!"<<endl;
// 	}
// 	else
// 	{
// 		cout<<nArr[nPos]<<endl;
// 	}

// 	int nArr[7] = {1,2,3,4,5,6,7};
// 	int nPos = FindNum(nArr,7);
// 	if (nPos == -1)
// 	{
// 		cout<<"不存在!"<<endl;
// 	}
// 	else
// 	{
// 		cout<<nArr[nPos]<<endl;
// 	}

// 	int nArr[7] = {7,6,5,4,3,2,1};
// 	int nPos = FindNum(nArr,7);
// 	if (nPos == -1)
// 	{
// 		cout<<"不存在!"<<endl;
// 	}
// 	else
// 	{
// 		cout<<nArr[nPos]<<endl;
// 	}
 	
	system("pause");
	return 1;
}

题目二

题目:

给出一个元素无序的数组,求出使得其左边的数都小于它,右边的数都大于等于它的所有数字

举例:

(1)1,2,3,1,2,0,5,6 : 输出5,6

(2)1,2,3,1,2,0,5,5 : 输出5(第一个5)

(3)1,2,3,4,5,6,7 : 输出1,2,3,4,5,6,7 

思路:

使用一个数组nArrMin[i]来保存[i,nLen-1]区间内的最小值。

使用一个变量nMax保存区间[0,i-1]的最大值。

对于第i个数,如果它满足nArr[i]大于左边的最大数nMax 且 小于右边的最小数nArrMin[i],则该数即为所求。

复杂度:时间:O(n),空间O(n)

代码

#include <iostream>
#include <assert.h>
#include <list>
using namespace std;

void FindNum(int nArr[],int nLen)
{
	assert(nArr && nLen > 0);
	int nPos = 0;
	int nMax = -0x3f3f3f3f;
	int nArrMin[100];
	nArrMin[nLen - 1] = nArr[nLen - 1];
	//遍历一遍数组,记录区间[i,len-1]的最小值,并保存到数组nArr[i]中
	for (int i = nLen - 2;i >= 0;i--)
	{
		if (nArr[i] > nArrMin[i + 1])
		{
			nArrMin[i] = nArrMin[i + 1];
		}
		else
		{
			nArrMin[i] = nArr[i];
		}
	}
	//遍历一遍数组,求解满足题意的数
	for (int i = 0;i < nLen;i++)
	{
		if (nArr[i] > nMax)
		{
			if (nArr[i] <= nArrMin[i])
			{
				//nArr[i]比左边数的最大值还要大且比右边数的最小值还要小,则输出
				cout<<nArr[i]<<" ";
			}
			nMax = nArr[i];
		}
		
	}
}

int main()
{
	int nArr[8] = {1,2,3,1,2,0,5,6};
	FindNum(nArr,8);//5 6
 	
// 	int nArr[7] = {1,2,3,4,5,6,7};
// 	FindNum(nArr,7);//1,2,3,4,5,6,7}

// 	int nArr[7] = {7,6,5,4,3,2,1};
// 	FindNum(nArr,7);//不存在

// 	int nArr[7] = {7,7,7,7,7,7,7};
// 	FindNum(nArr,7);//7

	system("pause");
	return 1;
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值