代码随想录算法训练营15期 Day 1 | 704 二分查找、27 移除元素

力扣 704 二分查找

 题目:

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 题解1:暴力解法

当我拿到这个题,不看数组中元素是否有序,直接在该数组中找到该元素,就直接一个for循环搞定,加上一个if判断语句,如果i对应的元素与target相等,输出i即可。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //暴力算法
        for(int i = 0 ; i < nums.size(); i++){
            if(nums[i] == target){
                return i;
                i++;
            }
        }
        return -1 ;
    }
};

题解2:carl哥解法 --要求是一个有序元素的整型数组

解法1:区间为左闭右开

这个地方要注意的是右边界,在while判断以及两个if判断结束后,左边界和右边界的取值问题,例如中间值大于目标值的时候,那么目标值是在左半区间,此时要考虑右边界的取值问题,但因为此题我们运用的是区间为左闭右开,那么右边界依然使用middle。但当中间值小于目标值时,目标值是在右半区间,左边界闭合,因此左边界我们的middle已经对比过了,不可能是目标值,所以此处左边界应该是middle+1.

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //左闭右开区间 [left,right)
        int left = 0 ;
        int right = nums.size();//不包含该点
        while(left < right){
            int middle = (left +right) / 2;
            if(nums[middle] > target){
                right = middle ;
            }
            else if(nums[middle] < target){
                left = middle + 1;
            }
            else {
                return middle;
            }
        }
        return -1 ;
    }
};

 解法2:区间为左闭右闭

这里我可以理解为区间左闭右闭,那么在中间值与目标值对比时,不管孰大孰小,左边界以及右边界都已经不是目标值了,此时我们均对middle加一处理即可。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //左闭右闭区间
        int left = 0 ;
        int right = nums.size() - 1 ;
        while(left <= right){
            int middle = (left + right) / 2 ;
            if(nums[middle] > target){
                right = middle - 1;
            }
            else if(nums[middle] < target){
                left = middle + 1;
            }
            else {
                  return middle;
            } 
        }
        return -1 ;
    }
};

力扣 27 移除元素

题目:

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

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解1:暴力解法

拿到这个题,加上知道数组元素不能直接移除,而是需要覆盖的知识。想到使用两个for循环来解决这个问题,一层for循环来找到这个目标元素,再用一层for循环将此目标元素后面的元素进行前移一位,进行覆盖,从而达到移除题中目标元素的目的。

这里要注意:因为需要移除的目标元素可能不止一个,因此在里层for循环前移后,要对当前目标元素下标i进行前移一位操作(因为不前移一位的话,当前i指的就是后面元素前移过后的第一个元素,要是这个元素是目标元素呢?),数组整体长度也要减1。再进行后面的寻找-前移覆盖。

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //暴力解法--两个for循环
        int size = nums.size();
        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 carl哥解法--双指针

利用一个for循环来达到两个for循环的效果,这里用到的就是快慢指针(SlowIndex 和 FastIndex)来做,精髓是if判断语句中的nums[fast] != val,轻松将目标值排除。

还有一个需要注意的点是:最后返回数组的新长度为什么是slow的值?

就是在最后一个快指针在老数组中找到非目标元素,将此元素赋值慢指针所在新数组,慢指针加一,但是后面没新元素输入到数组,又因为指针下标是从0开始,所以新数组的长度就是当前slow值。

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //双指针解法
        int slow = 0 ;
        for(int fast = 0 ;fast < nums.size() ; fast++){
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow++ ;
            }
        }
        return slow ;
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值