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

704.二分查找

题目的第一想法:

这道题对于我来说已经做过很多很多遍了,跟着carl哥学的一直坚持左闭右开或者左闭右闭,在任何时候都一样就可以完美应对这道题保证不出错!

实现代码:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        // 左闭右开版本
        int res;
        int left = 0;
        int right = nums.size();
        // left < right 因为左闭右开在left等于right时不满足条件,所以说不能相等
        while(left < right) {
            int mid = (left + right) / 2;
            if(nums[mid] > target) {
                // 右开,右边mid中值取不到
                right = mid;
            } else if(nums[mid] < target) {
                // 左闭,mid取不到所以说加一
                left = mid + 1;
            } else {
                // 这种情况已经相等返回答案了
                return mid;
            }
        }
        // 遍历完了还没找到返回-1
        return -1;
    }
};
class Solution {
public:
    int search(vector<int>& nums, int target) {
        // 左闭右闭版本
        int left = 0;
        int right = nums.size() - 1;
        // 左闭右闭,当left等于right的时候满足条件,必须使用<=
        while(left <= right) {
            int mid = (left+right)/2;
            if(nums[mid] > target) {
                // 右闭,mid位置不满足条件所以减一
                right = mid - 1;
            } else if(nums[mid] < target) {
                // 左闭,mid位置不满足条件所以加一
                left = mid + 1;
            } else {
                // 满足情况,直接返回答案
                return mid;
            }
            // 不满足条件,返回-1
        }
        return -1;
    }
    
};

遇到的问题:

在查看carl哥代码的时候,发现自己小细节出现了问题,carl哥代码如下:

// 版本一
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};
// 版本二
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
        while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target) {
                right = middle; // target 在左区间,在[left, middle)中
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,在[middle + 1, right)中
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};
​

卡哥在处理middle中值的时候,使用了一下方法:

int middle = left + ((right - left) >> 1);
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2

使用(right - left)>> 1右移运算符相对于除以2,相当于left加上中间值,就等同于(left + right)/ 2 ,但只有可以防止left+right时溢出,非常的细节,小本本记上!!

27.移除元素

题目的第一想法:

这到题也是经典中的经典,想当初在上数据结构的时候还在课堂上跟同学将过这个方法,导致同学都觉得我是大神,其实就是一个才学的小菜鸟罢了,这道题懂得这种换位思考就很好做,不考虑怎么去移除元素(数组移除元素需要移动后面大量元素),只需要考虑需要哪些元素满足条件然后保留下来即可。

代码实现:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        // slow指针表示与当前val不相等元素要插入的下标
        int slow = 0;
        // fast指针表示所遍历的元素下标,默认都从0开始
        int fast = 0;
        // nums.size()的值不会改变,这样ok
        while(fast < nums.size()) {
            // 不相等,表示不需要移除,放在slow下标
            if(nums[fast] != val) {
                nums[slow++] = nums[fast];
            }
            // 相等情况不做操作即可,相当与只要满足条件的元素
            fast++;
        }
        // 由于下标比长度小1,但slow是要插入的下标,所以说刚好对应其长度
        return slow;
    }
    
};

遇到的问题:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值