代码随想录训练营day01记录: 二分查找, 移除元素双指针

训练营的第一天, 上个月开始决定转码,马虎的学习了java的一些基础知识,看了几集韩顺平,赶感觉有本质上的提升,于是开始正式刷题. 第一天感觉还行, 虽然直接做题做不出来,但是看解法还是看得懂的,一定要坚持接下来两个月

今天的第一题是关于二分查找,binary search,前提是有序且不重复的

左闭右闭 和 左闭右开

两种解法,在一开始的index, while循环条件,和边界上皆有不同

首先介绍我写的左闭右闭:

看完carl哥的视频后还是比较理解的,但是上手写的时候有很多bug:

1.分清楚写的是数字还是index,这里的target, left和right是不同含义

2.分清楚条件,一开始就要判断target的合理性

3.右闭的话,判断条件就是小于等于

4. 在while循环判断是已经包括了middle(right),所以此时的middle已经不在新的区间里了,应该用middle-1/+1

5.>>是向右位移, 直接用left + (right - left)/2 一样(是为了防止数字过大超过边界)

6.这里有四种情况,大于,小于,等于(相当于直接找到了),遍历完都没有

class Solution {
    public int search(int[] nums, int target) {
        //左闭右闭
        if(target < nums[0] || target > nums[nums.length - 1]) {
            return -1;
        }

        int left = 0;
        int right = nums.length - 1; //这里由于右边闭合了

        while(left <= right) {
            int middle = left + ((right - left)>>1); //这里可以进一步了解
            if(nums[middle] > target) {
                right = middle -1; 
            } else if(nums[middle] < target){
                left = middle +1;
            } else if(nums[middle] == target){
                return middle;
                }
        }
        return -1;
    }
}

接下来是左闭右开:
在这里犯了几个低级错误

1.忘记给写 int middle = xxx了,记住java永远是面对对象的

2.记住对middle的赋值要放在循环里,不然是不会改变的

3.这里区别就是,right的定义就是num.size; left一样,但是right 直接=middle

class Solution {
    public int search(int[] nums, int target) {
        //左闭右开
        if(target < nums[0] || target > nums[nums.length - 1]){
            return -1;
        }

        int left = 0;
        int right = nums.length;  //这里右边是开的,所以直接num.length
        while (left < right) {
            int middle = left + (right - left)/2;
            if(nums[middle] < target) {
                left = middle + 1;
            } else if (nums[middle] > target) {
                right = middle;
            } else if (nums[middle] ==  target) {
                return middle;
            }
            
        }
        return -1;
    }
}

下一个是移除元素,有暴力解法和双指针解法

暴力解法:

这个对我来说反而不好理解,反正就是有两个for,第一个是来遍历每一个元素来匹配val;第二个是找到val后,将后面的元素覆盖到前面;

注意条件:
1. 判断如果找到val,进入遍历循环,新的数j, j=i+1,意思是val后面那个元素是j

2. 通过nums[j-1]=nums[j]来覆盖值,然后i--(后面的元素集体往前挪了,所以要减一复原),size--;

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

    }
}

双指针解法:

一个快指针:寻找新数组里所需要的元素(不含target的),也是index

一个慢指针:新数组的下标值就是slow

有以下注意事项:

1. 快指针无论什么情况都+1,慢指针符合条件才+1

2. 当快指针不等于target时,才是我们要的新数组元素

3.if里面要给slow代表的新数组赋值,也要给slow指针右移

4.这里如果不是if,slow就不会移动,也不会给新数组赋值,所以相当于删除了

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for(int fast = 0; fast < nums.length; fast++){
            if(nums[fast] != val){
                nums[slow] = nums[fast];   //这里要理解好,是给slow代表的新数组赋值
                slow++;                    //同时慢指针要向右移动         
            }
        }
        return slow;

    }
}

注意:这里总是会有sb小错误,比如nums总是写成num,甚至分号都忘记打。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值