Leetcode 704二分查找
带着问题去做题:
看视频时,老师反复强调了两点,都是关于边界处理的问题:1.循环变量while(left<right)还是while(left<=right),对应那两种区间?
2.right=midle-1还是right=midle???
之前看的时候一直记得这个,但没有理解;
先上代码:
/*--------对应左闭右闭[left,right]这种情况-------------------*/
class Solution {
public:
int binarySearch(vector<int>& nums, int target)
{
int left=0;
int right=nums.size()-1;
int midle;
int count=50;
//左闭右闭既[0,size-1],这样可以取到right而不会越界
/* t m */
/*[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]*/
while(left<=right){
midle=left+(right-left)/2;//???会不会出现midle+1而越界的情况呢?值得试一试
cout<<"mid="<<midle<<"; left="<<left<<"; right="<<right<<endl;
if(left==right)
cout<<"-----left=right,mid="<<midle<<endl;
if(target<nums[midle]){
right=midle-1;
}else if(target>nums[midle]){
left=midle+1;
}else if(target==nums[midle]){
return midle;
}
count--;//怕调试的时候循环卡死,设置了一个count
if(count<1){
cout<<"------------gameover-----------"<<endl;
break;
}
}
return -1;
}
int search(vector<int>& nums, int target) {
int ans=binarySearch(nums,target);
return ans;
}
};
如果左右区间的 开闭 确定下来了,就可以确定while里的循环,既
左闭右闭[left,right] 对应 while(left<=right),确定下来这个就可以确定左右边界怎么选,既left=midle+1,right=midle-1;
左闭右闭[left,right)对应 while(left<right);
接下来就可以确定,
之前一直没仔细看,如何定义开闭区间
以下面这个数组为例:
假设它叫nums:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
常见的三种情况 左闭右闭[left,right],左闭右开[left,right), 左开右闭(] 一般这种情况比较少.
左闭右闭则left=0,right=20;
左闭右开left=0, ** right=21;** 这里right是超出数组的;
下面来测试一下,如果不按这样写会出现什么情况:
1.令left<=right,left=midle,right=midle;
........
int right=nums.size()-1;
cout<<"target="<<target<<endl;
........
/* l m r */
/*[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]*/
while(left<=right){
midle=left+(right-left)/2;//???会不会出现midle+1而越界的情况呢?值得试一试
cout<<"l="<<left<<" ; mid="<<midle<<"; r="<<right<<endl;
if(left==right)
cout<<endl<<"-left=right,mid="<<midle<<endl;
if(target<nums[midle]){
right=midle;
}else if(target>nums[midle]){
left=midle;
}else if(target==nums[midle]){
return midle;
}
count--;
if(count<1){
cout<<"------------gameover-----------"<<endl;
break;
}
还是上面0-20的案例,发现末尾的元素20是取不到的,下面看看打印:
非常的恐怖,不加count就卡死 了
target=20;
l=0 ; mid=10; r=20
l=10 ; mid=15; r=20
l=15 ; mid=17; r=20
l=17 ; mid=18; r=20
l=18 ; mid=19; r=20
l=19 ; mid=19; r=20
l=19 ; mid=19; r=20
l=19 ; mid=19; r=20
l=19 ; mid=19; r=20
… …
l=19 ; mid=19; r=20
------------gameover-----------
-1
可以看到当运行到这里l=19 ; mid=19; r=20的时候,末尾的元素是取不到的;
2.令left<right,left=midle-1,right=midle+1;
省略代码:
同样也是取不到20
Leetcode27 移除元素
按照惯性的思维,自然就会想到用两个循环去解决它;
这里应该就是卡老师说的"暴力解法":
先上代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len=nums.size();
for(int i=0;i<len;){
/*--------------------------*/
if(nums[i]==val){
// cout<<"remove :"<<i<<" val:"<<val<<endl;
for(int j=i;j<len;j++)
{
//当元素在末尾时
if(j==len-1)
{
//cout<<"j=len-1;"<<endl ;
break;
}
nums[j]=nums[j+1];//要防止i+1越界,万一i=len-1怎么办?
}
len--;
continue;
}
i++;
/*-------------------------------------*/
}
//cout<<endl<<"---len="<<len;
return len;
}
};