# 数组理论基础

数组是存放在连续内存空间上的相同类型数据的集合,下标从 0 开始。

增添或者删除数组元素时不可避免的要移动其他元素的地址,因此数组的元素实际上不是删除,而是覆盖。

二维数组的内存空间地址在 C++ 中也是连续的。

# 二分查找

题目链接

难点:根据区间定义做边间处理

两种区间:左闭右闭 [left, right],左闭右开 [left, right)。两种区间内的元素都是相同的,只是表达方式不同。

# 左闭右闭写法

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int mid = 0;
        int left = 0, right = nums.size() - 1; // [left, right]
        while(left <= right) { //left == right 时,区间 [left, right] 依然有效
            mid = (left + right) / 2;
            if(target == nums[mid]) return mid; // 找到 target,返回下标
            else if(target > nums[mid]) left = mid + 1; //target 比中值大,找右半区间
            else right = mid - 1; //target 比中值小,找左半区间
        }
        return -1;
    }
};

# 左闭右开写法

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int mid = 0;
        int left = 0, right = nums.size(); // [left, right)
        while(left < right) { //left == right 时,区间 [left, right) 无效
            mid = (left + right) / 2;
            if(target == nums[mid]) return mid; // 找到 target,返回下标
            else if(target > nums[mid]) left = mid + 1; //target 比中值大,找右半区间
            else right = mid; //target 比中值小,找左半区间
        }
        return -1;
    }
};

# 移除元素

题目链接

# 暴力

时间复杂度O(n2)O(n^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 = i + 1; j < len; j++){
                    nums[j - 1] = nums[j];
                }
                len--;
                i--;
            }
        }
        return len;
    }
};

# 双指针法

  • 快指针:寻找非 val 值的元素作为新数组
  • 慢指针:更新的新数组最后元素下标位置
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0, fastIndex = 0;
        while(fastIndex < nums.size()) {
            // 当碰到要移除的元素时,快指针走,慢指针不动
            // 否则两指针一起移动
            if(nums[fastIndex] != val) {
                nums[slowIndex++] = nums[fastIndex];
            }
            fastIndex++;
        }
        return slowIndex;
    }
};

# 有序数组的平方

题目链接

数组有序,但包含负数。左端值平方后可能会成为最大值。

不能原地更新:原地更新的实质是暴力。以空间换时间,增添一个新数组来保存平方后的值。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result(nums.size(), 0);
        int n = nums.size() - 1;
        int left = 0, right = nums.size() - 1;
        while(left <= right) { // 最后还有两个元素要比较
            // 数组从右往左开始放值
            // 左右两值比较,最大的放入数组
            if(nums[left] * nums[left] < nums[right] * nums[right]) {
                result[n--] = nums[right] * nums[right];
                right--;
            }
            else {
                result[n--] = nums[left] * nums[left];
                left++;
            }
        }
        return result;
    }
};