算法Day01--数组--704. 二分查找,27. 移除元素,977. 有序数组的平方

总体感觉

今天刷了一天的题目了,晚上才开始干这几道题目,虽然都是元老级别的题目,也刷了不止一次了,但是也卡住了几下。

开始刷题

704. 二分查找

思路
基础题。我自己常用的是“左闭右闭”方法,一分钟不到写出来了。左闭右开写了一次,熟悉一下即可。

左闭右闭

class Solution {
    public int search(int[] nums, int target) {
        int n = nums.length;
        int left = 0;
        int right = n - 1;
        int mid = 0;
        while (left <= right) {
            mid = (left + right) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            }
        }
        return -1;
    }
}

左闭右开

class Solution {
    public int search(int[] nums, int target) {
        int n = nums.length;
        int left = 0;
        int right = n;
        int mid = 0;
        while (left < right) {
            mid = (left + right) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid;
            }
        }
        return -1;
    }
}
// 左闭右开——三个地方需要改变
// 1. right的定义,从right = n-1  改成  right = n
// 2. while的条件从left<=right  改成  left < right
// 3. 当target落在右区间,从right = mid + 1  改成 right = mid

推荐阅读:《代码随想录》
其实二分还有很多应用场景,有着许多变体,比如说查找第一个大于target的元素或者第一个满足条件的元素,都是一样的,根据是否满足题目的条件来缩小答案所在的区间,这个就是二分的本质。另外需要注意,二分的使用前提:有序数组
●二分的最大优势是在于其时间复杂度是O(logn),因此看到有序数组都要第一时间反问自己是否可以使用二分。
●关于二分mid溢出问题解答:
○mid = (l + r) / 2时,如果l + r 大于 INT_MAX(C++内,就是int整型的上限),那么就会产生溢出问题(int类型无法表示该数)
○所以写成 mid = l + (r - l) / 2或者 mid = l + ((r - l) >> 1) 可以避免溢出问题
●对于二进制的正数来说,右移x位相当于除以2的x几次方,所以右移一位等于➗2,用位运算的好处是比直接相除的操作快

27. 移除元素

思路
这道题卡住了。我想的是swap的方式,左指针找val,右指针找非val,当二者都找到的时候,左右交换。
但是这个方法,只能在非val的数量大于val的数量的时候用。总之还是有点问题的。等脑子清醒的时候,回头思考一下。
以下代码是思考不动之后,看题解的。

class Solution {
    public int removeElement(int[] nums, int val) {
        int n = nums.length;
        int left = 0;
        for(int right = 0;right<n;right++){
            if(nums[right]==val){
                continue;
            }
            nums[left++]=nums[right];
        }
        return left;
    }
}

977. 有序数组的平方

思路
这题记忆比较深刻,从后往前放数据,也就是双指针从原数组左右两边往中间靠拢,就不用主动去寻找正负数的分界线了。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int[] res = new int[n];
        int p = n - 1;
        int left = 0;
        int right = n - 1;
        while (left <= right) {
            int ll = nums[left] * nums[left];
            int rr = nums[right] * nums[right];
            if (ll >= rr) {
                res[p--] = ll;
                left++;
            } else {
                res[p--] = rr;
                right--;
            }
        }
        return res;
    }
}

拓展题

35. 搜索插入位置

34. 在排序数组中查找元素的第一个和最后一个位置

69. x 的平方根

367. 有效的完全平方数

26. 删除有序数组中的重复项

283. 移动零

844. 比较含退格的字符串

977. 有序数组的平方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值