704.二分查找·这是三个数的故事


left,middle,right

题目链接:https://leetcode.cn/problems/binary-search/

前提:数组有序  小->大
   数组无重复数
   使用语言:c++

寻找目标:target

思考路线:l–m–r
     m找target
     大小决定m
     向左or向右


方法一:左闭右闭式 [l,r]
    时间复杂度O(log(n));
    空间复杂度O(1);

class Solution {public:    int search(vector& nums, int target) {        int m;        int l=0;        int r=nums.size()-1;        while(l<=r){            m=(l+r)/2;            if(targetnums[m]){                l=m+1;//注意!            }            else if(target==nums[m]){                return m;            }        }        return -1;    }};

困难笔记:
  r=m和l=m造成了跳不出循环的问题
  原因:重复计算,陷入死循环
  理解:左闭右闭的形式下,左右边界值必定不包含前一次循环的中间值,因为前一次循环的中间值已经被判断过了。


方法二:左闭右开式 [l,r)
    时间复杂度O(log(n));
    空间复杂度O(1);

class Solution {public:    int search(vector& nums, int target) {        int m;        int l=0;        int r=nums.size();//区别        while(l<r){//因为[l,r)中l与r不能相等            m=(l+r)/2;            if(targetnums[m]){                l=m+1;//区别            }            else if(target==nums[m]){                return m;            }        }        return -1;    }};

区别笔记:这里的r应该是右边的数+1位


收获摘要:此题需要区分好查找时判断的边界问题,注意当次循环和下一次循环中三个数的联系。

越界问题:m=(l+r)/2
     int相加可能造成越界。
     可以用如下公式:
     m=l+(r-l)/2;

学习的文章链接:

https://programmercarl.com/0704.二分查找.html

学习的视频链接:

https://www.bilibili.com/video/BV1fA4y1o715


27、移除元素·无序好耶!doge


不容于nums数组的val

题目链接:https://leetcode.cn/problems/remove-element/

前提:O(1)额外空间
   元素顺序可以改变
   不需要考虑超出新长度的数组元素

想要知道:没有val数组有多长?

思考路线:是val就往后靠,让后边的上来


方法一:看到题目的第一想法,AC
    时间复杂度O(n);
    空间复杂度O(1);

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

思考笔记:应该也是暴力解法(本人最擅长暴力解doge),鉴于本题条件中输出数组是无序的,所以没有进行方法二中的覆盖操作。


方法二:暴力算法
    时间复杂度O(n^2);
    空间复杂度O(1);

class Solution {public:    int removeElement(vector& nums, int val) {        int l=nums.size();        int i=0;        int j;        for(i=0,i<l;i++){            if(nums[i]==val){                for(j=i+1;j<l;j++){//进行覆盖                    nums[j-1]=nums[j];                }                i--;//下一个数组元素也可能是val                l--;//数组长度-1            }        }        return l;    }};

方法三:双指针法
    时间复杂度O(n);
    空间复杂度O(1);

class Solution {public:    int removeElement(vector& nums, int val) {        int l=nums.size();        int i=0;        int slow=0;        for(int fast=0;fast<l;fast++){            if(nums[fast]!=val){//快指针指向的不是val就可以对慢指针指向的数组元素进行覆盖                nums[slow]=nums[fast];                slow++;            }        }        return slow;    }};

感悟笔记:双指针好快!


摘要笔记:双指针妙啊~~

学习的文章链接:

https://programmercarl.com/0027.移除元素.html

学习的视频链接:

https://www.bilibili.com/video/BV12A4y1Z7LP


今日学习时长:4h30min

Day01:好的开始,继续努力!