LeetCode704.二分查找
题目链接:702.二分查找
打卡第一天,学习了二分查找,第一次知道“左闭右闭”,“左闭右开”的概念,原来我之前一直写的都是左闭右闭。二分法有几个重要的点:1. 数组必须是有序的,如果对无序的数组进行查找还需要算上排序的时间复杂度;2. 在排序时,已经和val比较过的元素已经不需要了,在“左闭右闭”、“左闭右开”方式上有不同;3. 防止溢出——寻找middle时,如果数组较大且再次搜索的位置靠后,那么left+right就有可能会超过int类型的最大值,故寻找middle时最好用
//左闭右闭
int left=0;
int right = nums.size()-1;//左闭右闭区间,每一个数字都需要比较
while(left <= right){
int middle = left + (right - left)/2;
if (nums[middle] > target){
right = middle-1;
}
else if (nums[middle] < target){
left=middle+1;
}
else{
return middle;
}
}
return -1;
int left=0;
int right = nums.size();//左闭右开区间,右边的永远用不到
while(left < right){
int middle = left + (right - left)/2;
if (nums[middle] > target){
right = middle;
}
else if (nums[middle] < target){
left=middle+1;
}
else{
return middle;
}
}
return -1;
LeetCode27.移除元素
题目链接:27.移除元素
只能使用O(1)的额外位置,移除数组内与val相同的值。两种做法:1. 暴力移动,嵌套循环,外层循环找val相同的数,内层循环负责把原位置后面的数前移并覆盖原来的数。缺点,当与val相同的数连续排列且后面的数字多时时,每次都要移同一堆数,时间复杂度为O(n²)。
int size=nums.size();
for(int i=0;i<size;i++){
if(nums[i]==val){
for(int j=i;j++;j<size-1;j++){
nums[j]=nums[j+1];
}
i=i-1;
size--;
}
return size;
2. 双指针移动法:可以看作是两个指针,指针1指向原数组,指针2指向新数组(虚拟),想象成每一次把指针1指向的不同于val的数放进新数组中。但实际上新数组是从覆盖原数组得到的,从0开始,当不等于val时,指针1和指针2同时移动并且将指针1指向的数字赋值给指针2指向的位置;当等于val时,指针2不动,指针1动。
int secondInx=0;
for(int firstInx = 0; firstInx < nums.size(); firstInx++){
if (nums[firstInx] != val){
nums[secondInx] = nums[firstInx];
secondInx++;
}
}
return secondInx;
指针1只遍历数组一次,指针2没有后退,时间复杂度为O(n).