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

1.数组理论基础

文档讲解: 代码随想录

1.数组是存放在连续内存空间上的相同类型数据的集合(下标都是从0开始的)
2.删除或者增添元素的时候,需要考虑其他元素的地址,而且数组的元素不能删,只能覆盖
3.在C++中,二维数组在内存的空间地址是连续的,而JAVA并不是

2.704.二分查找

题目链接:二分查找
文档讲解: 代码随想录

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

这道题前段时间刚刚刷过,所以很容易的就写出来了。在写while循环的时候犹豫了一下,由于左闭右开,所以left无法等于right,因此确定为小于号。在写完左闭右开后,再写一下左闭右闭。

二分法的前提条件:(1)数组为有序数组(2)数组中无重复元素

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

扩展题

35.搜索插入位置

题目链接:35
文档讲解: 代码随想录

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length;//左闭右开
        while(left < right){
            int mid = left + (right - left) / 2;
            if(target > nums[mid]){
                //target在右边
                left = mid + 1;
            }
            else if(target < nums[mid]){
                right = mid;
            }
            else {
                return mid;
            }
        }
        return left;
    }

我对比了和代码随想录给出的答案,在未在数组中找到target的情况下,我是通过举例得到left,而答案是从逻辑上确认为right,结束while循环时left=right。复盘一下答案的逻辑:
(1)target出现在所有元素之前[0,0)
(2)target在数组中,return mid
(3)target不在数组中,但取值范围在[left,right)
(4)target出现在所有元素之后[left,right)
结合所有情况,左闭右开,应该是取不到的right

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

题目链接:34
文档讲解: 代码随想录

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = searchLeft(nums,target);
        int right = searchRight(nums,target);
        if(left == -2 || right == -2){
            return new int[] {-1,-1};
        }
        else if(right - left >= 2){
            return new int[] {left + 1,right - 1};//target==nums[mid]的时候更新边界
        }
        else return new int[] {-1,-1};
        }
    int searchLeft(int[] nums, int target){
        int left = 0;
        int right = nums.length - 1;//左闭右闭
        int leftBorder = -2;//记录leftBorder未被赋值的情况
        while(left <= right){
            //不应该搜索target在数组的位置,而应该不断用区间去逼近target
            int mid =left + (right - left) / 2;
            if(target <= nums[mid]){
                right = mid - 1;
                leftBorder = right; 
            }
            else{
                left = mid + 1;
            }            
        }
        return leftBorder;
    }
    int searchRight(int[] nums, int target){
        int left = 0;
        int right = nums.length - 1;//左闭右闭
        int rightBorder = -2;//记录rightBorder未被赋值的情况
        while(left <= right){
            //不应该搜索target在数组的位置,而应该不断用区间去逼近target
            int mid =left + (right - left) / 2;
            if(target >= nums[mid]){
                left = mid + 1;
                rightBorder = left; 
            }
            else{
                right = mid - 1;
            }            
        }
        return rightBorder;
    }
}

3.27.移除元素

题目链接:移除元素
文档讲解: 代码随想录

暴力解法:

class Solution {
    public int removeElement(int[] nums, int val) {
        int length = nums.length;
        for(int i = 0; i < nums.length; i++){
            if(nums[i] == val){
                length--;
                for(int j = i; j < nums.length - 1; j++){
                    nums[j] = nums[j + 1];
                }
                i--;
            }
        }
        return length;
    }
}

很奇怪,这样子跑的时间好长,思路应该是没错的。

双指针法:

class Solution {
    public int removeElement(int[] nums, int val) {
        int j = 0;
        for(int i = 0; i < nums.length; i++){
            if(nums[i] != val){
                nums[j++] = nums[i];//不为0的保留
            }
        }
        return j;//在循环中j最后会在赋值后执行+1
    }
}

这道题也是不久前刷过,双指针的思路没什么问题,但是在return j 的时候出错了,忘记了在循环中 j 会在赋值后自加1。

扩展题

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

题目链接:26

class Solution {
    public int removeDuplicates(int[] nums) {
       int len = 1;
       int val = nums[0];
       for(int i = 1; i < nums.length; i++){
        if(nums[i] != val){
            nums[len++] = nums[i];
            val = nums[i];
        }
       }
       return len;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值