代码随想录二刷 day01 | 704. 二分查找 27. 移除元素 26.删除有序数组中的重复项 80. 删除有序数组中的重复项 II

day01

      • 704. 二分查找
        • 第一种 左闭右闭
        • 第二种 左闭右开
      • 27. 移除元素
      • 26 删除有序数组中的重复项
      • 80. 删除有序数组中的重复项 II

704. 二分查找

题目链接
题目分析:有两种情况 左闭右闭,左闭右开,使用二分法 注重考虑边界问题

第一种 左闭右闭

以题目中的示例 1 解释一下这个题目[-1,0,3,5,9,12]

  • 左值为-1,右值为12 使用二分法后,第一次的中间值为nums[2] = 3
  • 如果目标值大于3时,则右值不变,左值变为中间值下标加一
  • 如果目标值小于3时,则左值不变,右值变为中间值下标减一
  • 如果找不到目标值,就返回-1

代码如下

class Solution {
public:
    //左闭右闭
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1; //定义target在左闭右闭的区间里,即:[left, right)
        while(left <= right){
            int middle = left + ((right - left) >> 1);
            if(nums[middle] > target){
                right = middle -1;
            }
            else if(nums[middle]  < target){
                left = middle + 1;
            }
            else{
                return middle;
            }
            
        }
        return -1;
    }
};

第二种 左闭右开

将示例2改为[-1,0,3,5,9,12)

  • 左值为-1,右值为12 使用二分法后,第一次的中间值为nums[2] = 3
  • 如果目标值大于3时,则右值不变,左值变为中间值下标加一
  • 如果目标值小于3时,则左值不变,右值变为中间值
  • 如果找不到目标值,就返回-1

代码如下

class Solution {
public:
    //左闭右开
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size();  //定义target在左闭右开的区间里,即:[left, right)
        while(left < right){    //左闭右开时,要将=去掉
            int middle = left + ((right - left) >> 1); //  >> 1  相当于除2
            if(nums[middle] > target){
                right = middle ;
            }
            else if(nums[middle]  < target){
                left = middle + 1;
            }
            else{
                return middle;
            }
            
        }
        return -1;
    }
};

27. 移除元素

题目链接
题目分析:可以采用双指针的思想。一个快指针,一个慢指针。如果快指针遇到了不等于val的值,就将其下标放入慢指针中,最后返回慢指针。

代码如下:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
            int slowindex = 0;
            for(int fastindex = 0; fastindex < nums.size();fastindex++){
                if(val != nums[fastindex]){
                    nums[slowindex] = nums[fastindex];
                    slowindex++;
                }
            }

            return slowindex;
    }
};

26 删除有序数组中的重复项

题目链接
解题思路 :和上一题比较相似,慢指针先不动,快指针进行遍历,快指针将不重复的,存储到慢指针中,最后返回慢指针。假设数组 nums 的长度为 n。将快指针 fast 依次遍历从 1n−1的每个位置,对于每个位置,如果nums[fast]≠nums[fast−1],说明 nums[fast]和之前的元素都不同,因此将 nums[fast]的值复制到 nums[slow],然后将 slow 的值加 1,即指向下一个位置。

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int n = nums.size(); 
        if(n == 0){  //使用剪枝法
            return 0;
        }
        int slowindex = 1;
        for(int fastindex = 1 ; fastindex < n; fastindex++){
            if(nums[fastindex] != nums[fastindex-1]){
                nums[slowindex++] = nums[fastindex];

            }
        }
        return slowindex;
    }
};

80. 删除有序数组中的重复项 II

题目链接
解题思路: 本题要求相同元素最多出现两次而非一次,所以我们需要检查上上个应该被保留的元素 nums[slow−2] 是否和当前待检查元素nums[fast] 相同。当且仅当 nums[slow−2]=nums[fast] 时,当前待检查元素 nums[fast] 不应该被保留(因为此时必然有 nums[slow−2]=nums[slow−1]=nums[fast]。最后,slow 即为处理好的数组的长度

代码如下:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int n = nums.size(); 
        if(n <= 2){  //使用剪枝法
            return n;
        }
        int slowindex = 2;
        for(int fastindex = 2 ; fastindex < n; fastindex++){
            if(nums[fastindex] != nums[slowindex-2]){
                nums[slowindex++] = nums[fastindex];

            }
        }
        return slowindex;
    }
};

你可能感兴趣的:(算法训练营,leetcode,算法,数据结构)