Day1
1.掌握二分法边界值判断,是根据写法来的;
2.删除数组元素的双指针和暴力解法;
3.灵活使用双指针方法
704 二分法
以前对于边界的问题非常纠结,到底是<还是<=,以及是mid还是mid-1。
通过视频讲解,得知二分法的两种常见写法:左闭右闭,左闭右开。
边界情况是根据以上两种写法来定的,对边界情况的判断本质上是使得区间是合理的。
两种写法的区别在于while里面是left <= right(左闭右闭)还是left < right(左闭右开)。
左闭右闭写法:
class Solution { public: int search(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; //左闭右闭 while(left <= right){ int mid = (left + right) / 2; if(nums[mid] < target){ left = mid + 1; } else if (nums[mid] > target){ right = mid - 1; } else return mid; } return -1; } };
左闭右开写法:
class Solution { public: int search(vector<int>& nums, int target) { int left = 0, right = nums.size(); //左闭右开 while(left < right){ int mid = (left + right) / 2; if(nums[mid] < target){ left = mid + 1; } else if (nums[mid] > target){ right = mid ; } else return mid; } return -1; } };
主要改动了四个地方:
207 移除元素
使用双指针的方法对元素进行“删除”(“删除”本质上是覆盖,数组的元素不能被直接删除,当然这里vector也不是数组而是容易,但是我们是当做数组来实现的)
定义一个快指针和一个慢指针,快指针用于找到我们要的值,并赋给慢指针,慢指针相当于在一个新数组上。
双指针写法:
class Solution { public: int removeElement(vector<int>& nums, int val) { //双指针 时间复杂度O(n) int slow = 0; for ( int fast = 0; fast < nums.size(); fast++){ if(nums[fast] != val){ nums[slow] = nums[fast]; slow ++; } } return slow; } };
暴力解:
class Solution { public: int removeElement(vector<int>& nums, int val) { //暴力解 int length = nums.size(); for(int i = 0; i < length; i++){ if(nums[i] == val){ for(int j = i + 1; j < length; j++){ nums[j - 1] = nums[j]; } i--; length--; } } return length; } };
977.有序数组的平方
难点在于平方后还要保持有序,这该怎么实现?
依然可以用暴力法
但仔细观察发现,数组两端数据的绝对值最大,中间最小,所以我们可以用双指针
class Solution { public: vector<int> sortedSquares(vector<int>& A) { int k = A.size() - 1; vector<int> result(A.size(), 0); for(int i = 0, j = A.size() - 1; i<=j;){ if(A[i]*A[i] < A[j] * A[j]){ result[k] = A[j] * A[j]; k --; j --; } else{ result[k] = A[i] * A[i]; k --; i++; } } return result; } };