【LeetCode题目详解】704.二分查找,27. 移除元素 day1

本文章代码以c++为例!

一、力扣第704题:二分查找

题目链接:704.二分查找-力扣(Leetcode)

【LeetCode题目详解】704.二分查找,27. 移除元素 day1_第1张图片

 二分查找在学校的课程里面有学过,然后在看了一下代码随想路在b站的视频,更深刻的理解二分查找,知道了二分查找有两种写法,左闭右闭即[left, right],或者左闭右开即[left, right)。

我写的是第一种方法,左闭右闭即[left, right]。

区间的定义这就决定了二分法的代码应该如何写,因为我定义target在[left, right]区间,所以有如下两点:

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

 代码如下:

class Solution {
public:
    int search(vector& nums, int target) {
    int low = 0, high = nums.size() - 1;
        while(low <= high){
            int mid = (high - low) / 2 + low;
            int num = nums[mid];
            if (num == target) {
                return mid;
            } else if (num > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return -1;
    }
};
  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)

二、力扣第27题:原地移除元素

题目链接:27. 移除元素 - 力扣(Leetcode)【LeetCode题目详解】704.二分查找,27. 移除元素 day1_第2张图片

 

1.思路一:

其实对于这道题而言,我一开始最先想到的方法是直接两层for循环暴力解法,一个for循环遍历数组元素 ,第二个for循环更新数组。暴力解法的时间复杂度是O(n^2),这道题目暴力解法在leetcode上是可以过的。

代码如下:

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int s = nums.size();
        for (int i = 0; i < s; i++) {
            if (nums[i] == val) { 
                for (int j = i + 1; j < s; j++) {
                    nums[j - 1] = nums[j];
                }
                i--; s--; 
            }
        }
        return s;
    }
};

 后来看了代码随想录的b站视频,知道了还有第二种解法,用双指针法(快慢指针法)来解,这样子大大降低了时间复杂度,从O(n^2)变成了O(n),双指针是是算法中的一种技巧,双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。最常见的双指针算法有两种:一种是,在一个序列里边,用两个指针维护一段区间;另一种是,在两个序列里边,一个指针指向其中一个序列,另外一个指针指向另外一个序列,来维护某种次序。
在视频里卡哥解释了如何利用双指针法来解决这道题,通过一个快指针和慢指针在一个for循环下来完成两个for循环的工作。

代码如下:(有解析)

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

注意这些实现方法并没有改变元素的相对位置!

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

打卡day 1

你可能感兴趣的:(leetcode,算法,职场和发展,c++)