思路
只要是这种查找的题都有一个通解就是遍历,显然如果是面试那么offer就要了,代码自行写,本质就是一个二维数组
从题可以看出每一行都是左右递增,每一列都是上下递增,那么我们就可以利用这个特性,
target和第一行的最后一个元素比,那么会出现俩种状况
- targe大于最后元素
因为是左右递增,那么targe就不会在当前行,直接排除当前行
- targe小于最后元素
因为是上下递增那targe就不在当前列,直接排除当前列
代码:
class Solution {
public:
bool Find(int target, vector<vector<int> > array)
{
//1.查找本质就是排除
//2.数组从左到右、从上到下都是递增的
//3.利用这一特性就可以一次排除一行或者一列
int row =0;//行
int lin=array[0].size()-1;//列
while(row<array.size()&&lin>=0)
{
if(array[row][lin]<target)//小于说明不在这一行
{
row++;
}
else if(array[row][lin]>target)//大于说明不在这一列
{
lin--;
}
else
{
return true;//上面的情况都不是说明找到了
}
}
return false;//循环下来没有找到说明没有
}
};
题目链接
思路
题说是非降序的数组,且是旋转过来的如 1,2,3,4 --> 3,4,1,2可以看出如果相邻的俩个数前一个比后一个大那么那个值就是最小数,但是这个本质也是遍历,就是少走几次循环罢了
代码:
class Solution {
public://双指针法
int minNumberInRotateArray(vector<int> rotateArray)
{
int prev=0;
int next=1;
if(rotateArray[prev]<rotateArray[next]&&rotateArray[next]==rotateArray[rotateArray.size()-1])//处理特殊情况,只有俩个数据,或者只有一个数据的情况
{
return rotateArray[prev];
}
while(next<rotateArray.size())
{
if(rotateArray[prev]>rotateArray[next])
{
break;
}
prev=next++;
}
return rotateArray[next];
}
};
代码:
class Solution
{
public://二分法
int minNumberInRotateArray(vector<int> rotateArray)
{
int left=0;
int right=rotateArray.size()-1;
while(left<right)//条件
{
if(rotateArray[left]<rotateArray[right])//特殊情况[1,2,2,2,2],这个也叫非递减。。。。,也可以把判断写在二分失效这,建议写着效率高
{
return rotateArray[left];
}
if(left+1==right)//当左右left与right相邻时right一定是最小值
{
break;
}
int middle=(left+right)/2;
if(rotateArray[left]==rotateArray[right]&&rotateArray[right]==rotateArray[middle])//该数列中多个重复数字,二分法失效
{
int mini=rotateArray[left++];
while(left<=right)
{
if(rotateArray[left]<mini)
{
mini=rotateArray[left];
}
left++;
}
return mini;
}
if(rotateArray[left]<=rotateArray[middle])//reft~middle属于一个区间
{
left=middle;
}
else
{
//middle~right属于一个区间
right=middle;
}
}
return rotateArray[right];
}
};
上述思路中推荐使用二分法,你如果觉得不好把控,你可以写双指针法,那么面试官会觉得你利用了原有条件,会给你加分,实在没有看出来你也可以使用sort,顺便问问面试官可不可以调用系统的接口,不行的话你在秀一下自己写快排的能力面试官看你写的不错也会给你加分,但是写出二分法offer到手
题目链接
思路
看着名字是不是很不一样哈哈哈,其实也可以叫保卫萝卜法
1. 选取第一个数字为弓箭手,且他有一个血条初始值1
2 .遇到相同数则加血,不同则扣血,当血被扣完时,谁杀死“弓箭手”,谁就是新的弓箭手,如此往复
3. 预防数组中没有值出现次数超过一半长度的值
代码:
//塔防法
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
int guard=numbers[0];
int hp=1;
for(int i =1;i<numbers.size();i++)//寻找幸存的弓箭手
{
if(numbers[i]==guard)
{
hp++;
}
else
{
hp--;
}
if(hp==0)//更换哨兵
{
guard=numbers[i];
hp=1;
}
}
int count=0;
for(int i =0;i<=numbers.size();i++)//判断是否存在,可以不写题目标注一定有解
{
if(numbers[i]==guard)
{
count++;
}
}
return count>numbers.size()/2?guard:0;
}
};
题目链接
这篇博客之后你需要认识一个概念就是查找的本质就是排除,效率高就是一次排除的多(二分),效率低(遍历)