寻找数组中无序的部分,并返回索引。

    题目:《程序员面试金典 (第5版)》P314

    给定一个整数数组,编写一个程序,找出索引m 和 n,只要将 m 和 n 之间的元素排好序,整个数组就是有序的。注意:n-m 越小越好,即找出符合条件的最短序列。

    提示:假设数组有序部分按照从小到大的方式排列。比如输入int a[]={1,2,4,7,10,11,7,12,6,7,16,18,19},返回m=3,n=9. 输入 int b[]={1,5,7,8,0,3,1,5,8,19},返回m=0,n=7.

//计算数组下标从start到end中最小的数
int minArray(int *a,int start,int end)
{
	int res=a[start];
	for(int i=start+1;i<=end;i++)
	{
		if(a[i]<res)
			res=a[i];
	}
	return res;
}

//计算数组下标从start到end中最大的数
int maxArray(int *a,int start,int end)
{
	int res=a[start];
	for(int i=start+1;i<=end;i++)
	{
		if(a[i]>res)
			res=a[i];
	}
	return res;
}

//返回false表示不存在索引m和n可以满足题目要求
//返回false时,给m和n赋值-1
bool FindIndex(int a[],int len,int &m,int &n)
{
	if(a==nullptr || len<=1)
	{
		m=-1;
		n=-1;
		return false;
	}
	if(len==2)
	{
		if(a[0]<=a[1])//整个数组有序
		{
			m=-1;
			n=-1;
			return false;
		}
		else//整个数组无序
		{
			m=0;
			n=1;
			return true;
		}
	}

	//len>=3时,初始化left和right
	//left为有序数组的结尾,right为有序数组的开始。这点很重要。
	int left=0,right=len-1;
	while(left<=len-2)
	{
		if(a[left]>a[left+1])
			break;
		left++;
	}
	while(right>=1)
	{
		if(a[right]<a[right-1])
			break;
		right--;
	}
	if(left>=right)//整个数组有序
	{
		m=-1;
		n=-1;
		return false;
	}

	//left+1==right是一种特殊情况
	if(left+1==right)
	{
		if(left>=1)
			left--;
		if(right<=len-2)
			right++;
	}

	//判断还能不能左右移动
	bool lmove=true,rmove=true;
	if(left==0)
	{
		lmove=false;
	}
	if(right==len-1)
	{
		rmove=false;
	}

	int l_max,r_min,m_max,m_min;	

	do{
		if(left>=0)
			l_max=a[left];
		else
			l_max=0x80000000;//int最小值
		if(right<=len-1)
			r_min=a[right];
		else
			r_min=0x7fffffff;//int最大值
		m_max=maxArray(a,left+1,right-1);
		m_min=minArray(a,left+1,right-1);

		if(m_min>=l_max && m_max<=r_min)
			break;

		//正确:m_min>=l_max
		if(m_min<l_max)
		{
			int tmp=left-1;
			while(tmp>=0)
			{
				if(m_min>=a[tmp])
				{
					left=tmp;
					break;
				}
				else
					tmp--;
			}
			if(tmp<0)
			{
				left=-1;
				lmove=false;
			}
		}

		//正确:m_max<=r_min
		if(m_max>r_min)
		{
			int tmp=right+1;
			while(tmp<=len-1)
			{
				if(m_max<=a[tmp])
				{
					right=tmp;
					break;
				}
				else
					tmp++;

			}
			if(tmp>len-1)
			{
				right=len;
				rmove=false;
			}
		}

	}while( lmove || rmove );

	if(left==-1 && right==len)//整个数组无序
	{
		m=0;
		n=len-1;
		return true;
	}

	m=left+1;
	n=right-1;
	return true;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值