首页 > 编程语言 >代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。

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

时间:2022-11-16 15:59:15浏览次数:86  
标签:27 target nums int 随想录 middle right 移除 left

今日任务

数组理论基础,704. 二分查找,27. 移除元素

1数组理论基础

文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

  • 数组内存空间的地址是连续的

2 704. 二分查找

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

文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html

视频讲解:https://www.bilibili.com/video/BV1fA4y1o715

情况1

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(int[] nums, int target) {
        int left = 0;
        int right = nums.length -1;
        while (left <= right){
            int mid = left + (right - left)/2;
            if(target < nums[mid]){
                right = mid -1;
            }else if(target > nums[mid]){
                left = mid + 1;
            }else{
                return mid;
            }
        }
        return -1;
    }
}

情况2

定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。

有如下两点:

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length;
        while (left < right){
            int mid = left + ((right - left)>>1);
            if(target < nums[mid]){
                right = mid;
            }else if(target > nums[mid]){
                left = mid + 1;
            }else{
                return mid;
            }
        }
        return -1;
    }
}

left + ((right -left) >> 1) == (left + right) /2

 

>>: 二进制右移

举个例子: 1010 >> 1 == 0101

1010 十进制 10

0101 十进制 5

综上 >> 1 作用相当于除二

 

所以 left + ((right -left) >> 1) ==> left + ((right -left)/2)

==> left + right/2 -left/2 ==> left/2 + right/2 ==> (left + right) /2

总结

搞清楚边界的定义,循环中注意边界值的变化;

 

3 27. 移除元素

题目建议: 暴力的解法,可以锻炼一下我们的代码实现能力,建议先把暴力写法写一遍。 双指针法 是本题的精髓,今日需要掌握,至于拓展题目可以先不看。

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

文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html

视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP

3.1 暴力循环

class Solution {
    public int removeElement(int[] nums, int val) {
        int len = nums.length;
        for(int i = 0;i< len;i ++){
            if(nums[i] == val){
                for(int j = i +1;j< len;j ++){
                    nums[j-1] = nums[j];
                }
                len --;
                i--;
            }
        }
        return len;
    }
}

时间复杂度是O(n^2)

 

3.2双指针法

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

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置
class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for(int fast = 0;fast < nums.length;fast ++){
            if (val != nums[fast]){
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

第一天总结:

逐渐回忆之前的知识(数组特点+双指针),以及用java解答问题。用时2.5h,希望之后加快速度。

标签:27,target,nums,int,随想录,middle,right,移除,left
From: https://www.cnblogs.com/gaoyuan2lty/p/16896149.html

相关文章