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<int>& nums, int target) {
        int m;
        int l=0;
        int r=nums.size()-1;
        while(l<=r){
            m=(l+r)/2;
            if(target<nums[m]){
                r=m-1;//注意!
            }
            else if(target>nums[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<int>& nums, int target) {
        int m;
        int l=0;
        int r=nums.size();//区别
        while(l<r){//因为[l,r)中l与r不能相等
            m=(l+r)/2;
            if(target<nums[m]){
                r=m;//区别
            }
            else if(target>nums[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<int>& 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<int>& 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<int>& 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:好的开始,继续努力!

posted on 2022-10-26 22:41  Tink白草  阅读(958)  评论(0编辑  收藏  举报