代码随想录day1:数组part1,二分查找&移除数组中元素

day1 数组&二分查找

数组理论

参考
https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
注意数组的内存空间地址(是否连续?)

二分查找

参考代码随想录文章 https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html

二分查找的核心是由区间的定义决定边界条件(while循环结束条件)和边界点的变化!!!

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

https://leetcode.cn/problems/binary-search/

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

        int l = 0, r = nums.length - 1;
        while (l <= r) {
            int m = l + (r - l >> 1);
            if (nums[m] > target) r = m - 1;
            else if (nums[m] < target) l = m + 1;
            else return m;
        }
        return -1;
    }
}
35.搜索插入位置

https://leetcode.cn/problems/search-insert-position/description/

解法1:找>=目标值的最左位置

class Solution {
    public int searchInsert(int[] nums, int target) {
        // 找不到的话ans插入位置是右边界
        int l = 0, r = nums.length - 1, ans = nums.length;
        while (l <= r) {
            int m = l + (r - l >> 1);
            if (nums[m] >= target) {
                ans = m;
                r = m - 1;
            } else l = m + 1;
        }
        return ans;
    }
}

解法2:普通二分,处理所有四种情况

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;

        // 定义target在左闭右闭的区间,[low, high]
        int low = 0;
        int high = n - 1;

        while (low <= high) { // 当low==high,区间[low, high]依然有效
            int mid = low + (high - low) / 2; // 防止溢出
            if (nums[mid] > target) {
                high = mid - 1; // target 在左区间,所以[low, mid - 1]
            } else if (nums[mid] < target) {
                low = mid + 1; // target 在右区间,所以[mid + 1, high]
            } else {
                // 1. 目标值等于数组中某一个元素  return mid;
                return mid;
            }
        }
        // 2.目标值在数组所有元素之前 3.目标值插入数组中 4.目标值在数组所有元素之后 return right + 1;
        return high + 1;
    }
}
34.在排序数组中查找元素的第一个和最后一个位置

https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int n = nums.length;
        int l = 0, r = n - 1, ans = 0;
        int[] res = new int[]{-1, -1};
        // 防止数组越界
        if (n == 0) return res;
        while (l <= r) {
            int m = l + (r - l >> 1);
            if (nums[m] >= target) {
                ans = m;
                r = m - 1;
            } else l = m + 1;
        }
        if (nums[ans] != target) return res;
        else res[0] = ans;

        l = 0;
        r = n - 1;
        ans = 0;
        while (l <= r) {
            int m = l + (r - l >> 1);
            if (nums[m] <= target) {
                ans = m;
                l = m + 1;
            } else r = m - 1;
        }
        res[1] = ans;
        return res;
    }
}

数组中移除元素

27.移除元素

https://leetcode.cn/problems/remove-element/

解法1:暴力两层循环

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;
    }
}

解法2:双指针

快慢指针:

  • 快指针:寻找新数组中的元素,即不含有目标数的元素
  • 慢指针:新数组下标(想象指向一个虚拟的新数组)
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];
        }
        return slow;
    }
}
26.删除有序数组中的重复项

快慢指针

  • 比较 slow 和 fast 位置的元素是否相等。

  • 如果相等,fast 后移 1 位

  • 如果不相等,将 fast 位置的元素复制到 slow + 1 位置上,slow 后移 1 位,fast 后移 1 位
    重复上述过程,直到 fast 等于数组长度。

  • 返回 slow + 1,即为新数组长度。与上一题27题不一样的原因是,27题是 slow 更新后++,所以 slow 就是数组长度,26题是 slow 先后移 1 位再更新,所以返回值要 + 1(slow++与++slow的区别)

class Solution {
    public int removeDuplicates(int[] nums) {
        int slow = 0;
        for (int fast = 1; fast < nums.length; ) {
            if (nums[slow] == nums[fast])
                fast++;
            else if (nums[slow] != nums[fast])
                nums[++slow] = nums[fast++];
        }
        return slow + 1;
    }
}
  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值