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

题目链接:704. 二分查找 - 力扣(LeetCode)

今日的第一题是数组的二分查找;

二分时应当给出左侧以及右侧,

本题的关键实际上就是对于终结时刻的判断——即while什么时候结束
以及一个最重要的问题

关键在于,当我们在查找到中间值后,取中间值的两侧,中间值所在的位置应当被舍弃,理解了这一点才能更好的理解到我们在左闭右闭以及左闭右开的区间中的对于right 和 left 的更新的处理

循环不变量

*对于区间的定义,区间定义的关键即为不变量,要在二分查找的过程中,保持不变量,在每次while寻找中对于每次边界的处理都要坚持根据区间的定义进行操作

通常对于区间的定义有两种:

  • 左闭右开[left,right)

    在此种情形下,有如下两点应当注意:

    • 在结束循环的判断中,应当使用while(left < right) ,这是由于left = right 是无法做到的
    • if(nums[mid] > target)中 right 更新为 mid,因为当前nums[mid] ≠ target, 因此可以直接将区间的右端定义为mid的当前值

    具体的左闭右开代码书写如下:

    public class Solution {
        public int search(int[] nums, int target) {
            //最应当做的应该首先是特殊情况处理
            if(nums.length==0){
                return -1;
            }
            //对于左闭右开的情况的处理
            int left = 0;
            int right = nums.length;
            int mid;
            while(left < right){
                //mid常态化变化
                mid = (left + right) / 2;
                if(nums[mid] < target){
                    left = mid+1;
                }
                else if(nums[mid] > target){
                    right = mid;
                }
                else{
                    return mid;
                }
            }
            return -1;
    
        }
    }
    
  • 左闭右闭[left,right]

    此时有如下两点需要注意:

    • 在while结束的判断中,应当使用while(left ≤ right),这是出于确实存在着left == right 的情形去实际考虑的
    • if(nums[mid] > target) 中 right需要赋值为 mid -1, 因为当前的nums[mid] 一定不是target,则接下来需要查找的左区间结束的下标位置为 mid-1。 同理,left在其对应的情形下应当赋值为 mid + 1

具体的左闭右闭代码书写如下:

public class Solution {
    public int search(int[] nums, int target) {
        //最应当做的应该首先是错误处理
        if(nums.length==0){
            return -1;
        }

        //定义左边、右边,每次查找后修改查找的边界
        int len = nums.length;
        int left = 0;
        int right;

        //此处定义为左闭右闭区间
        right = len-1;

        int mid = (left+right)/2;
        //当左右相邻时结束,存在左==右情况,故此处为<=
        while(left <= right){
            //mid应该成为常态形变化变量,每次都应该更改
            mid = (left + right) / 2;
            //中间位置的值更小一些
            if(nums[mid] < target){
                left = mid + 1;
            }
            //中间值更大
            else if(nums[mid] > target){
                right = mid - 1;

            }
            else{
                return mid;
            }

        }
        return -1;

    }
}

27.移除元素

题目链接:27. 移除元素 - 力扣(LeetCode)

看到这道题,我心中最朴素的想法就是直接使用后来的元素去替代原位置上的元素,即两次遍历,这样就能够完成题目条件,将需要移除的元素后面的元素全部向前移动一位。

代码如下:

public class Solution {
    public int removeElement(int[] nums, int val) {
        int sum = nums.length;//sum代表了整个数组中的元素个数
        for(int i = 0; i < sum;i++){
            if(nums[i] == val){
                //此处应当注意是否会发生栈溢出
                for(int j = i+1; j < sum;j++){
                    nums[j-1] = nums[j];
                }
								
                i--;//由于少了一个元素,因此应当重新遍历刚刚移动过来的元素
                sum--;//注意sum中的元素个数是在动态变化的,如果不是如此使用,可能会造成栈溢出等问题?
            }
        }
        return sum;
    }
}

双指针法

通过一个快指针和一个慢指针在一个for循环下完成两个for循环的工作

  • 快指针:寻找新数组的元素,新数组就是不含有目标元素的数组
  • 慢指针:指向更新的新数组下标的位置

删除过程如下图:

https://tva1.sinaimg.cn/large/008eGmZEly1gntrds6r59g30du09mnpd.gif

代码如下:

public class Solution {
    public int removeElement(int[] nums, int val) {
        //双指针法处理如下:
       int slowIndex = 0;
       for(int fastIndex = 0; fastIndex < nums.length;fastIndex++){
           if(val != nums[fastIndex]){
               nums[slowIndex++] = nums[fastIndex];
           }
       }
       return slowIndex;
    }
}

本日是我跟随代码随想录进行训练的第一天,时间也是来的颇为匆忙,在这为期两个月的时间中,我相信自己定会有所收获。
未来漫长,一定努力。
祝你,也祝我

第二十二天的算法训练营主要涵盖了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题,题目要求在给定的数组中找到长度最小的子数组,
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值