目录
第一次用LeetCode刷题,属实有点懵。在VS上写好了直接搬过去运行是不行的。
LeetCode它不需要写main函数,也不需要我们判断什么输入输出。
它是直接将题目封装成一个类或者一个函数,测试代码时直接调用的。
咱就是说高级!
好了咱说题目
题目一、二分查找
虽然看起来很简单,但是还是有一些坑的。
无脑刷题的我上去直接就是一顿暴力算法,遍历数组。
然后就是让我震惊的通过率
暴力有风险啊
论看题的重要性,以及可以得出二分查找的效率是真的会提高!O(logN)不是吹牛
int search(int* nums, int numsSize, int target){
int left=0;
int right=numsSize-1;
int mid = (numsSize-1)/2;
while(left<=right){
if(nums[mid]==target){
return mid;
}
if(nums[mid]<target){
left=mid+1;
}else{
right=mid-1;
}
mid = (left+right)/2;
}
return -1;
}
这里需要注意的是,mid的大小,不能是mid=numsSize不然你会得到:
因为数组会越界呜呜呜
题目二、第一个错误版本
首先就是一个大写的没看懂题
输入n是告诉我们总共有几个版本,根据常识版本号是连续的且是递增的。
bool isBadVersion(version) 这是一个判断是否是坏的版本的函数。
如果该版本是坏的,则返回true!!!!
接下来就是踩坑记录了:
数组越界!
如果使用mid = (begin+end)/2 的话很可能会溢出,这是因为,如果begin和end都很大那相加当然更大咯
解决办法:int mid = low + (high - low) / 2;
注意最好不要 mid = left/2 + right/2
原因下个题再说呜呜呜,反正很痛苦就对了!
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
int begin=0;
int end=n;
int mid=(begin+end)/2;
while(begin<=end){
bool isbadbefore=isBadVersion(mid-1);
bool isbadnow=isBadVersion(mid);
bool isbadbehind=isBadVersion(mid+1);
if(isbadbefore==false && isbadnow==true){
return mid;
}
if(isbadnow==false && isbadbehind==true){
return mid+1;
}
if(isbadnow==false){
begin=mid+1;
}else{
end=mid-1;
}
mid=begin/2 + end/2;
}
return n+1;
}
};
这是我写的代码,就是在二分查找的基础上多加了一个判断。
根据第一个坏版本的位置特点,就是第一个坏版本的前一个一定是好的。
But!!我也参考了其他大佬的代码,发现新大陆!
就是说可以只对一边进行判断,如果中间位置是好版本那第一个坏版本一定在右边,如果中间位置是坏版本,那第一个坏版本一定在左边。
当循环结束时,也就是left>right的时候,坏版本一定在left位置!
刚刚发现的一个规律!
就是如果按照mid = (left+right)/2 的方法计算mid,那mid一定不会落在right的位置,除非left和right指向同一个位置!!
这是因为整数的除法是直接舍弃小数点的,所以不可能有
所以结束循环的时候,left一定指向第一个坏版本!
bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
int left = 0;
int right = n-1;
int mid = right/2;
while(left<=right){
if(isBadVersion(mid)==false){
left=mid+1;
}else{
right=mid-1;
}
mid = left + (right-left)/2;
}
return left;
}
};
题目三、搜索插入位置
1、在变化mid的时候,因为会遇到第二题的溢出问题所以,我自以为机智的改成了
mid = left/2 + right/2; 然后就成功的死循环了。真开心!
这是因为int的除法本来就是向下取整的,两个向下取整就相当于在中间位置偏移了2个元素所以就死循环了(其实我也不是很懂)
还是举例子把!
就是如果left在3,right在3,则按照mid = left/2 + right/2来算,mid=3/2+3/2=2;
然后left=mid+1=2+1=3;然后就成功出不了循环了!
所以需要用mid = left + (left + right)/2;
2、就是数组越界的问题!
那就是一个屡教不改啊!朋友
给right赋初值的时候,right = nums.size()-1;
答应我以后不要忘记了减一好吗!
3、就是最后出循环的问题;
就是记住好吧,因为能用二分查找的数组都是已经排好序的。
所以!如果是升序排列的话,那么未找到元素出循环的时候left一定指向查找元素应该插入的位置!
想不清楚的话,自己推一下就好了啊!动脑不如动笔!
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
int mid = right/2;
while(left<=right){
if(nums[mid]==target)
return mid;
if(nums[mid]<target)
left=mid+1;
else right=mid -1;
mid = (left+right)/2;
}
return left;
}
};
综上!今天又是开心的一天呢!
再见!