代码随想录算法训练营第一天| LC704. 二分查找、LC27. 移除元素

LeetCode 704 二分查找

题目链接:704. 二分查找

个人做题感想:拿到题目之后,自己独立写完并且ac了,自己写的具体代码

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0, right=nums.size()-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]==target){
                return mid;
            }else if(nums[mid]>target){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return -1;
    }
};

看完卡哥视频代码随想录书相应部分后,才知道原来二分查找还有那么多细节,突然感觉自己ac的代码很多细节都没有注意,有可能这次写对下次就写不对,或者自己没有遵循一定规则去写错误了然后调试浪费大量时间。

具体细节部分:① while(left<right)还是while(left<=right) ② right=middle还是right=middle-1
进行上述细节的书写时候,就要知道循环不变量的规则,这里的循环不变量就是区间的定义,在while循环中,每一次边界的处理都要根据区间的定义来操作,区间大小和个数不能多也不能少。

二分法中区间的定义有两种,一种是左闭右闭即[left, right],另一种是左闭右开[left, right),才发现原来自己单独ac的代码是第一种写法,自己也比较倾向于第一种写法

下面是两种写法具体代码

//左闭右闭区间写法,始终保持这个循环不变量,不能多,也不能少
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;
        while(left<=right){     //注意
            int mid = left +(right-left)/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;
        int right=nums.size();
        while(left<right){   //注意
            int mid = left +(right-left)/2;
            if(nums[mid]<target){
                left=mid+1;
            }else if(nums[mid]>target){
                right=mid;   //注意
            }else{
                return mid;
            }
        }
        return -1;
    }
};

LeetCode 27 移除元素

题目链接:27. 移除元素

个人做题感想1:拿到题目之后,由于自己以前接触过双指针的题目和看过这道题目,所以第一想法就想到了双指针做法,且自己独立写完并且ac了,不过相对卡哥给的代码,自己写的代码很low,而且感觉思路也不是很清晰,自己写的具体代码如下:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n=nums.size();
        int slow=0,fast=0;
        while(fast<n){
            if(nums[fast]==val){
                fast++;
                continue;
            }else{
                nums[slow++]=nums[fast++];
            }
        }
        return slow;
    }
};

看完卡哥视频代码随想录书相应部分后,自己的思路突然更加清晰了,一定要注意快慢指针的定义。特别注意:双指针法(快慢指针)在这个题目中的定义如下:快指针:寻找新数组的元素,也就是不含目标元素的数组的元素 慢指针:指向和更新数组下标的位置,注意上述指针都是在原数组上操作的
具体代码如下:

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

个人做题感想2:由于自己一下子想到了快慢指针写法,就没有想暴力解法了,这不是一个好习惯,很多题目做不出的时候用暴力至少能够做出来,然后再在暴力法的基础上进行优化,看完卡哥暴力解法思路以及代码实现后,代码实现很值得学习,自己没写出来暴力解法代码:

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

个人做题感想3:由于本题目基于元素顺序可以改变的这一前提条件,最后卡哥给出了相向双指针法,代码写法特别是那几个while的判断以及if的判断写法很值得推敲和学习,有可能也会用在其它题目中:

/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {
public:
    int removeElement(vector<int>& 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一定指向了最终数组末尾的下一个元素
    }
};

今天按照步骤做下来包括写博客一共花了三个小时左右(题目比较简单且熟悉所以很快就解决了),由于第一次在csdn种用markdown写博客,所以这篇博客写了比较长时间,不过是自己空闲时候写的。

贵在坚持,加油,共勉

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值