挑战两个月常见算法类型刷一遍(C++)|第一天

一、二分查找

基础知识:数组。内存上是连续的。C++中就是vector和array。其实vector底层实现就是array

核心:就是关注“循环不变量”——区间。左闭右闭、左闭右开。注意等于号的问题。

习题:力扣704题。力扣

//挑战下ACM模式(后续调试好电脑IDE加上)
//左闭右闭
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 - left) / 2);  
            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 left = 0;
        int right = nums.size();
        while (left < right) {
            int middle = left + ((right - left) >> 1);  
            if (nums[middle] > target) {
                right = middle;
            } else if (nums[middle] < target) {
                left = middle + 1;
            } else {
                return middle;
            }
        }
        return -1;
    }
};

二、移除元素

核心点:数组在内存地址上是连续存放的,不能被真实删除掉,只能是覆盖掉。

解法一:暴力解法。别问,问就是循环,再问就告诉你两个for循环。

             需要注意的是删除元素后的变量有哪些?因为是覆盖,所以找到一个数组大小就减一;然后外层循环变量那里,代码注释说的是参照《代码随想录》中的解释,很好理解,举个例子:数组:0 5 0 4 0 0 1 5 删除0.手动写下过程就会发现i不减一会忽略掉一个0.

// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        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--; // 因为i以后的元素都往前移动了一位,所以i要减一
                size--; // 每找到一个数组大小就减一
            }
        }
        return size; 
    }
};

解法二:双指针法。以后数组、链表、字符串处理会经常用的一种方法。

// 同向双指针、快慢指针
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        int size = nums.size();
        for (int fastIndex = 0;; fastIndex < size; fastIndex++) {
            if (nums[fastIndex] != val) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};
// 相向双指针法。改变了元素相对位置,但是移动的最少元素
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int leftIndex = 0;
        int rightIndex = nums.size() - 1;
        while (leftIndex <= rightIndex) {
            // 找出左边等于目标值的元素
            while (leftIndex <= rightIndex && nums[leftIndex] != val) {
                leftIndex++;
            }
            // 找出右边不等于目标值的元素
            while (leftIndex <= rightIndex && nums[rightIndex] == val) {
                rightIndex--;
            }
            // 将右边不等于val的位置的值覆盖到左边等于val的位置
            if (leftIndex < rightIndex) {
                nums[leftIndex++] = nums[rightIndex--];
            }
        }
        return leftIndex; // leftIndex一定指向数组末尾元素的下一个元素
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值