在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。
2012-04-25 01:05
369 查看
注:本题解可能不唯一。如何查找所有解?
算法:设数组a[0...n-1],设有左右两个游标i,j。左游标右移过程中的最大值为max,右游标左移过程中的最小值为min。则当i==j时且min>=max,则有解,其中一解就是a[i]
算法是这样的:
1)初始化i = 0,j = n-1,max = a[0],min = a[n-1]
2)如果a[i] < max 则i++
3)如果a[j] > min 则j--
4)如果a[i] >= max 且a[j] <= min,则需要使i++或使j--
当a[i+1] <= min时,i++,并更新max;否则如果i++,就会造成左侧数大于右侧数无法求得解
当a[j-1] >= max时,j--,并更新min;否则由于此时的max可能已经被更新,如果j--就会造成右侧数小于左侧数,无法得解
由于当j - i == 1时上面两种情况不可能同时发生,因此避免了两个游标更新后造成j < i的问题,但是可能会出现上面两种情况均不发生的情形,此时说明j-i > 1,且max > min;此时需要对i进行回溯。
此种算法时间复杂度为O(n), 空间复杂度为O(n)。
PS:如果要获得所有满足条件的解,需另设置两个监测站,q1,q2,分别存储i和j最后一次跳变前得位置。所有满足条件的解即为(q1,q2)。不包括q1和q2
算法:设数组a[0...n-1],设有左右两个游标i,j。左游标右移过程中的最大值为max,右游标左移过程中的最小值为min。则当i==j时且min>=max,则有解,其中一解就是a[i]
算法是这样的:
1)初始化i = 0,j = n-1,max = a[0],min = a[n-1]
2)如果a[i] < max 则i++
3)如果a[j] > min 则j--
4)如果a[i] >= max 且a[j] <= min,则需要使i++或使j--
当a[i+1] <= min时,i++,并更新max;否则如果i++,就会造成左侧数大于右侧数无法求得解
当a[j-1] >= max时,j--,并更新min;否则由于此时的max可能已经被更新,如果j--就会造成右侧数小于左侧数,无法得解
由于当j - i == 1时上面两种情况不可能同时发生,因此避免了两个游标更新后造成j < i的问题,但是可能会出现上面两种情况均不发生的情形,此时说明j-i > 1,且max > min;此时需要对i进行回溯。
此种算法时间复杂度为O(n), 空间复杂度为O(n)。
// 在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。 bool FindValue(int data[], int n, int& find) { int maxTemp = data[0], minTemp = data[n-1]; int i = 0, j = n-1; int* temp = new int ; // 回溯使用 while(i != j) { temp[i] = maxTemp; // 回溯条件 if(maxTemp > minTemp) { --i; if(i < 0) break; maxTemp = temp[i]; --j; minTemp = min(data[j], minTemp); continue; } bool bFlag1 = data[i+1] >= maxTemp; bool bFlag2 = data[j-1] <= minTemp; // 优先滑动不符合的当前滑标 if(!bFlag1) { ++i; } if(!bFlag2) { --j; } // 此处可能需要修正左侧最大值,右侧最小值 if(bFlag1 && bFlag2) { bool bL = false; bool bR = false; // 只有当左侧游标的下一值满足此条件时才右移游标 if(data[i+1] <= minTemp) { ++i; maxTemp = data[i]; bL = true; } // 此时可能已经更新了左游标,判断右游标是否需要移动 if(data[j-1] >= maxTemp) { --j; minTemp = data[j]; bR = true; } // 如果两个游标都不能移动,需要回溯 if(!bL && !bR) { // 回溯 --i; if(i < 0) break; maxTemp = temp[i]; --j; minTemp = min(data[j], minTemp); } } } if(i == j) find = data[i]; delete[] temp; return (i == j); }
PS:如果要获得所有满足条件的解,需另设置两个监测站,q1,q2,分别存储i和j最后一次跳变前得位置。所有满足条件的解即为(q1,q2)。不包括q1和q2
相关文章推荐
- 在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。
- 算法题27 在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。
- 在一个int数组里查找出所有这样的数,它大于等于左侧所有数,小于等于右侧所有数。
- 在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 微软等数据结构+算法面试100题(9)--在一个int 数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。
- 在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 在一个int数组里查找出所有这样的数,它大于等于左侧所有数,小于等于右侧所有数。
- 在数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 在数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数[#63]。
- 在数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 在数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 在数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 在数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 在数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数[#63]
- [面试] 在数组查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- [面试] 在数组查找这样的数,它大于等于左侧所有数,小于等于右侧所有数
- 一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它
- 一个int数组, 比如 array[],里面数据无任何限制,要求求出 所有这样的数array[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现
- 一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。