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

LeetCode 704.二分搜索

题目链接:704.二分搜索

踩坑:由于长时间没有coding,对于很多算法以及概念脑袋都不是很清醒,直接开始写的时候竟然一直在往递归的方面想(脑子里全是归并排序的分治方法),对二分法已经没有一个清晰的过程印象了,越想越迷糊。之后去看了卡哥的视频,看了一点就豁然开朗了,直接AC。

思路:想要解决二分法一定要先清楚的描述出二分法,很多人可能只是脑子里有个概念,大概知道是什么意思,所以一写就废当有一个升序的数组,以及一个target,我们首先需要将target与中间值对比,根据结果来更新区间范围,这就是二分法的核心。落实到细节会出现你这个区间是左闭右闭还是左闭右开区间(一般是上述两种情况),确定了针对的区间类型,才能指导具体代码的实现。

代码:

// 对于左闭右闭
class Solution {
public:
    int search(vector<int>& nums, int target) {
    	// 左闭右闭区间的右边界应该是有效的索引
        int right = nums.size() - 1;
        int left = 0;
        // 左闭右闭区间的右边界是可以与左边界重合的
        while(left <= right)
        {
            int middle = (left + right) / 2;
            // 当明确中间值比target大时,右边界应更新在中间索引的前一位,小时同理
            if(nums[middle] > target) right = middle - 1;
            else if(nums[middle] < target) left = middle + 1;
            else return middle;
        }
        return -1;
    }
};
// 对于左闭右开
class Solution {
public:
    int search(vector<int>& nums, int target) {
    	// 左闭右开区间的右边界应该是有效的索引的后一位
        int right = nums.size() ;
        int left = 0;
        // 左闭右开区间的右边界是不可以与左边界重合的
        while(left < right)
        {
            int middle = (left + right) / 2;
            // 当明确中间值比target大时,右边界应更新在中间索引,小时同理
            if(nums[middle] > target) right = middle;
            else if(nums[middle] < target) left = middle + 1;
            else return middle;
        }
        return -1;
    }
};

LeetCode 27.移除元素

题目链接:27.移除元素

踩坑:这道题的难点主要在于不能使用额外的空间,必须在数组原地进行操作。那其实思路就只有两种了,一种是移动覆盖,一种是交换。我自己使用的是交换策略,出问题的点在于与移除元素交换位置的元素应该保证是在其后面的,否则会出现将要移除的元素交换到前面的问题。

思路:

  1. 我自己的思路是交换,即遍历数组,将需要移除的元素与其后面的最后一个不是目标元素的元素交换位置,同时并不是每交换一个位置数组长度减一,而是在寻找末尾可交换元素的过程中一直减一,因为如果不可交换的元素也没有遍历的必要。(感觉自己的方式确实是有点绕)
  2. 卡哥的解法是移动覆盖,但是使用双指针(非常佩服),即一快一慢,两个指针。快指针指向老数组中的元素,慢指针指向新数组中的元素。我认为这方法的核心是,快指针走过的部分就变得毫无意义,可以任意更改。

代码:

// 我自己的思路
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len = nums.size();
        for(int i = 0; i < len; i++)
        {
            if(nums[i] == val)
            {
                for(int j = len - 1; j >= i; j--)
                {
                    if(nums[j] != val)
                    {
                        int t = nums[j];
                        nums[j] = nums[i];
                        nums[i] = t;
                        break;
                    }
                    // 放在末尾的元素没有价值,不需要遍历
                    len--;
                }
            }
        }
        return len;
    }
};
// 卡哥的方法
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];
            }
        }
    return slow;
    }
};
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值