代码随想录算法训练营Day01|704.二分查找、27.移出元素


文章目录

  • 数组
  • 704.二分查找
    • 1.左闭右闭区间
    • 1.左闭右开区间
  • 27.移出元素
    • 1.暴力解法
    • 2.双指针法
  • 总结


数组

  • 数组是存放在连续内存空间上的相同类型数据的集合。
  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续的。
  • 数组的元素是不能删的,只能覆盖。

704.二分查找

题目描述: 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

1.左闭右闭区间

第一种写法,我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right] (这个很重要非常重要)。
区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下两点:

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=。
  • if(nums[middle] > target) right 要赋值为 middle -1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

代码随想录算法训练营Day01|704.二分查找、27.移出元素_第1张图片

class Solution {
    public int search(int[] nums, int target) {
        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 if (nums[mid] > target)
                right = mid - 1;  
        }
        return -1;
    }
}

1.左闭右开区间

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

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的。
  • if(nums[middle] > target) right 更新为middle,因为当前nums[middle] != target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]

代码随想录算法训练营Day01|704.二分查找、27.移出元素_第2张图片

class Solution {
    public int search(int[] nums, int target) {
        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 if (nums[mid] > target)
                right = mid;  
        }
        return -1;
    }
}

在Java中,表达式 (right-left) >> 1 表示的是将right 和left的差值向右移动 1 位。
例如:left=0,right=4时:

  1. 计算括号内的差值:(4-0)=4
  2. 将这个结果向右移动 1 位。在二进制中,4 表示为 100。向右移动一位相当于除以 2 的幂,即除以 2: 4 > > 2 = 4 2 1 = 4 2 = 2 4>>2=\frac{4}{2^{1}}=\frac{4}{2}=2 4>>2=214=24=2

27.移出元素

题目描述: 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

1.暴力解法

两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。

2.双指针法

双指针法又称为快慢指针法,通过一个快指针和慢指针,在一个for循环下完成两个for循环的工作。
快指针: 寻找新数组元素,新数组就不含有目标元素的数组
慢指针: 指向更新 新数组下标的位置

代码随想录算法训练营Day01|704.二分查找、27.移出元素_第3张图片

class Solution {
    public int removeElement(int[] nums, int val) {
        int fastIndex = 0;
        int slowIndex;
        for(slowIndex = 0; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != val) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
}

总结

以上就是今天要学习的内容,二分查找的重点是区间设定(左闭右开or左开右闭),针对不同的区间设定判定循环时的符号和右边界如何更新;移出元素的重点是掌握双指针法。

你可能感兴趣的:(代码随想录算法集训营,算法,数据结构,java,leetcode)