目录
二维数组中的查找3/6
参考:https://www.cnblogs.com/silentteller/p/11762414.html(右上角查找)
参考:https://www.nowcoder.com/questionTerminal/abc3fe2ce8e146608e868a70efebf62e?f=discussion(左下角查找)
思路:
采用右上角元素进行比较:
1 行rows = array.size();列cols = array.size(); 右上角元素下标array[0][cols - 1]
2 i 扫描行,i <rows; j扫描列, j>=0
3 当target>当前值,向下查找;i++
当target <当前值,向左查找;j--
直至找到/扫描完,退出循环
【查找】
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
// array是二维数组,这里没做判空操作
int rows = array.size();//行
int cols = array[0].size();//列
int i=0,j=cols-1;//右上角角元素坐标
while(i<rows && j>=0){//使其不超出数组范围
if(target>array[i][j])
i++;//查找的元素较小,往下找
else if(target<array[i][j])
j--;//查找元素较大,往左找
else
return true;//出口A,找到
}
return false;//出口B,没找到
}
};
旋转数组的最小数字
【递归】和【二分法】
二分法思路:
1 左指针l = 0,右指针r = size-1;mid = l + (r - l)/2;
2 (以下用l代称左指针指向的数字,r,mid同理)
因为原序列是非递减(含有重复数字),所以最小值可能出现在右边(不绝对,例如不旋转时候,最小值在最左边),所以这里选择mid和r进行比较。
如果mid > r,说明左边有序非递减,如{3412}或{333111},那么最小值在右侧,要去右边的半段中找,l = mid + 1;
如果mid < r,说明右边有序非递减,如{4123}或{311133},但是mid可能就是最小值,比如{4123},要注意这里的边界。
特殊情况:右边非递减序列的起点可能是现在的mid,也可能在[l, mid]区间内,所以 r = mid;相当于去[l,mid]中找最小 值,因为 此时的mid是右边最小值。
如果mid = r,出现重复元素,r--
3 当l < r 的时候一直做2的循环
跳出循环条件: l = r,这个时候l和r指向同一个元素,不用再进行比较
4 返回r指针指向的数组的值
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int left = 0, right = (int)rotateArray.size() - 1;
while(left < right){//注意小于号,当左右相当,即同一元素,不用比较大小
int mid = left + (right - left) / 2;
if(rotateArray[mid] > rotateArray[right]) left = mid + 1;//左半段有序,比如{3423}
else if(rotateArray[mid] < rotateArray[right]) right = mid;//右半段有序,但是mid可能就是最小值,比如{3123},要注意这里的边界
else right--;//删除重复
}
return rotateArray[right];
}
};
递归方法:
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.empty())
return 0;
return find(rotateArray, 0, rotateArray.size()-1);
}
int find(vector<int> &nums, int l, int r){
if(nums[l] < nums[r] || l == r)//【易错】
return nums[l];
int mid = l + (r - l) / 2;
return min(find(nums, l, mid), find(num