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

学习任务:


Leetcode704.二分查找

难度:简单 | 相关标签:数组、二分查找

  • 题目: 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
  • 思路:
    1. 设定左右指针
    2. 找出中间位置,并判断该位置值是否等于 target
    3. nums[mid] == target 则返回该位置下标
      nums[mid] > target 则右侧指针移到中间
      nums[mid] < target 则左侧指针移到中间
  • 注意:
    1. 这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件。
    2. 写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。一定好好好区分掌握。
    3. 注意mid的写法:int middle = left + ((right - left) / 2);可以防止溢出 ,等同于(left + right)/2
  • 代码: 左闭右闭
class Solution {
    public int search(int[] nums, int target) {
        int i = 0;
        int j = nums.length - 1; 
        while(i <= j){
            int mid = (i + j) / 2;
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] > target){
                j = mid - 1; 
            }else{
                i = mid + 1;
            }
        }
        return -1;
    }
}
  • 反思: 在区间开闭上迟疑了很久,一定好好好区分和掌握两种不同的二分写法

Leetcode27.移除元素

难度:简单 | 相关标签:数组、双指针

  • 题目: 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

    1. 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
    2. 返回 k。
  • 思路: 暴力破解就是用后面的元素覆盖前面需要移除的元素;如果是双指针定义快慢指针,快指针指的是无论是否找到 val 都正常往后移动但是慢指针就不是这样了,遇到val 它就不更新了

  • 注意:

    1. 定义快慢指针:
      快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
      慢指针:指向更新 新数组下标的位置
  • 代码:
    暴力破解: 两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组

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--;  // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
                size--;  // 此时数组的大小-1
            }
        }
        return size;
    }
}

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

class Solution1 {
    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++;
            }
        }
        return slow;
    }
}
//相向双指针法
class Solution2 {
    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length - 1;
        while(right >= 0 && nums[right] == val) right--; //将right移到从右数第一个值不为val的位置
        while(left <= right) {
            if(nums[left] == val) { //left位置的元素需要移除
                //将right位置的元素移到left(覆盖),right位置移除
                nums[left] = nums[right];
                right--;
            }
            left++;
            while(right >= 0 && nums[right] == val) right--;
        }
        return left;
    }
}
  • 反思: 一开始暴力也没写出来,想着如果找到与val相等的值,是后面一个值往前移动覆盖掉这个值,但是如果后面的值也是等于val怎么办呢,然后就没思路了。一定要好好掌握双指针的方法。
  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值