代码随想录算法训练营第23期day1|704. 二分查找、27. 移除元素

目录

一、(leetcode 704)二分查找

1)左闭右开

2)左闭右闭

二、(leetcode 27)移除元素

1)暴力解法

2)双指针法

快慢指针法

双向指针


  • 数组是存放在连续内存空间上的相同类型数据的集合

1)数组下标都是从0开始的。

2)数组内存空间的地址是连续的——在删除或者增添元素的时候,要移动其他元素的地址

  • 注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组

一、(leetcode 704)二分查找

力扣题目链接

状态:暴力解法AC,新学二分查找,掌握区间边界条件

题目里提到“有序的(升序)整型数组 nums”,且无重复元素,可以考虑二分查找

1)左闭右开

代码随想录算法训练营第23期day1|704. 二分查找、27. 移除元素_第1张图片  

class Solution {
public:
    int search(vector& nums, int target) {
        int left = 0;
        int right = nums.size(); 
        while (left < right) { // 因为left==right的时候,在[left, right)是无效空间,所以使用<
            int middle = left + (right - left)/2;
            if (nums[middle] > target) {
                right = middle; // target
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,在[middle + 1, right)中
            } else { // nums[middle] == target
                return middle;
            }
        }
        return -1;
    }
};

2)左闭右闭

代码随想录算法训练营第23期day1|704. 二分查找、27. 移除元素_第2张图片

class Solution {
public:
    int search(vector& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else { // nums[middle] == target
                return middle; 
            }
        }
        return -1;
    }
};

区间的定义就是不变量,在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则 

二、(leetcode 27)移除元素

力扣题目链接

状态:暴力解法、快慢指针法AC,双向指针思路不清需回顾

1)暴力解法

代码随想录算法训练营第23期day1|704. 二分查找、27. 移除元素_第3张图片

2)双指针法

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

快慢指针法

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置

代码随想录算法训练营第23期day1|704. 二分查找、27. 移除元素_第4张图片

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

并没有改变元素的相对位置 

双向指针

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int leftIndex = 0;
        int rightIndex = nums.size() - 1;
        while (leftIndex <= rightIndex) {
            // 找左边等于val的元素
            while (leftIndex <= rightIndex && nums[leftIndex] != val){
                ++leftIndex;
            }
            // 找右边不等于val的元素
            while (leftIndex <= rightIndex && nums[rightIndex] == val) {
                -- rightIndex;
            }
            // 将右边不等于val的元素覆盖左边等于val的元素
            if (leftIndex < rightIndex) {
                nums[leftIndex++] = nums[rightIndex--];
            }
        }
        return leftIndex;   // leftIndex一定指向了最终数组末尾的下一个元素
    }
};

你可能感兴趣的:(代码随想录二刷,算法)