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

 澄o的第一天代码随想录记录

704. 二分查找

自己看到这道题 之前见过两三次 自己慢慢的复述出来思路就写出来大概的二分算法

代码随想录的答案精化算法细节 我在自己的代码里也加上

记得第一次看二分算法很难 一点都不懂 但是既然选择码就要坚持走下去 果然看了两三遍就会了 希望自己可以多拓展多敲敲 多回头复习巩固一下

Java代码:

class Solution{
    public int search(int[] nums, int target){
        //避免当target小于nums[0] nums[nums.length - 1]时多次运算
        //特殊规避情况
        if(target < nums[0] || target > nums[nums.length - 1]){
            return -1;
        }
        int left = 0,right = nums.length - 1;
        //左闭右闭
        while(left <= right){
            int mid = left + ((right - left) >> 1);//防止数据过大溢出
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] < target){
                left = mid + 1;
            } else{
                right = mid - 1;
            }
        }
        return -1;//没找到
    }
}

27. 移除元素

 第一下想到暴力解法 遍历数组找到val 再用j = i + 1的j指针(下一个元素)直接覆盖nums[i](当前元素值) 更新位置也删除了元素 需要把数组长度n-1保持元素数目一致 同样把i也减一 

搬用gpt的解释

i-- 的目的是为了确保在当前位置的元素被覆盖后,外层循环能够重新检查这个新覆盖的元素。这是因为在内层循环中,你将后面的元素向前移动来覆盖当前等于 val 的元素,这意味着当前索引 i 的位置现在有了新的值,这个新值可能也需要被移除。

        /*假设数组 nums[3, 2, 2, 3],并且我们要移除所有值为 2 的元素

  1. 第一次循环,i = 0nums[0] = 3,不等于 val(假设 val = 2),所以不做任何操作。
  2. 第二次循环,i = 1nums[1] = 2,等于 val,所以我们进入内层循环。
  3. 在内层循环中,我们将 nums[2](值为 2)移动到 nums[1] 的位置,覆盖了原来的 2。现在 nums 变成了 [3, 3, 2]
  4. 因为我们执行了 n--,所以数组的有效长度减少了,n 从 4 变成了 3
  5. 然后我们执行 i--,这样 i 从 2 变回 1。这是因为 nums[1] 现在有了新的值(原来的 nums[2]),这个值可能也需要被移除。

如果没有 i--,循环将继续检查下一个元素(nums[2]),而不会重新检查 nums[1] 的新值,这可能会导致漏掉需要移除的元素。

因此,i-- 确保了每个新覆盖的元素都能被重新检查,以确保所有等于 val 的元素都被移除*/

Java代码:

class Solution {
    public int removeElement(int[] nums, int val) {
        int n = nums.length;
        for(int i = 0; i < n; i++){
            if(val == nums[i]){//若发现删除元素 就把数组集体往前移动一位
                for(int j = i + 1;j < n; j++){
                    nums[j - 1] = nums[j];
                }
                i--;//因为下标i的元素也往前移动一位了 所以i--回退1位
                n--;//此时数组大小再-1
            }
        }
        return n;//返回数组长度
    }
}

双指针?

不会做捏 看看代码随想录

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

针对这道题分为快慢指针和相向指针法

快慢指针分别指:快指针:寻找新数组元素,新数组指不含有目标元素的数组

慢指针:指向更新 新数组下标的位置 

个人认为快慢指针用于覆盖元素和位置移动

Java代码:

class Solution {
    public int removeElement(int[] nums, int val) {
        //快慢指针
        int slowindex = 0;
        for(int fastindex = 0; fastindex < nums.length; fastindex++){
            //如果fastindex对应数组的元素值是val 则跳过当前元素下标并继续下一个元素
            //如果fastindex对应数组元素值不是val 则跳过当前元素
            //nums[slowindex++] = nums[fastindex];的意义是
            //用nums[fastindex](快指针对应元素值)的值覆盖当前slowindex下标对应元素值 完成值交换
            //再给slowindex++
            //把慢指针右移一位 完成位置右移
            if(val != nums[fastindex]){
                nums[slowindex++] = nums[fastindex];
            }
        }
        return slowindex;
    }
}

相向指针法

看了一下gpt的解释 加上自己的思考 捋清楚思路了 先把right指针移动到从右开始第一个不是val的元素上 如果nums[right] == val 那就直接right-- 删除此位置和元素 豁然开朗捏

left和right的内部操作可以理解

Java代码:

class Solution {
    //个人理解 不如快慢指针清晰 但是尝试接受双指针
    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length - 1;
        while(right >= 0 && nums[right] == val) right--;
        //把right指针移到从右数第一个值不为val的位置 例子[3 2 4 2] val == 2
        while(left <= right){
            if(nums[left] == val){//left位置的元素需要移除
                nums[left] = nums[right];//把right位置的元素移到left
                //再把right下标位置删除 right--
                right--;
            }
            left++;//left右移
            while(right >= 0 && nums[right] == val) right--;
            ////将right移到从右数第一个值不为val的位置
        }
        return left;
    }
}

OK了结束打卡 去看看左神的算法课~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值