算法训练1-day1

29 阅读2分钟

今天的三道题都是数组与双指针相关

  1. 704. 二分查找 简单题,唯一要注意的就是区间选择会影响后续的循环跳出条件,以及right的改变 AC代码:
//左闭右闭
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        int mid = left + (right - left) / 2;
        while (left <= right) {
            if (nums[mid] == target)
                return mid;
            else if (nums[mid] > target) // 在mid的左边
                right = mid - 1;
            else // 在mid的右边
                left = mid + 1;
                
            mid = left + (right - left) / 2;
        }
        return -1;
    }
};

// 左闭右开区间
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size();  // 注意:右边界是开区间,所以是nums.size()
        while (left < right) {    // 左闭右开时,left == right 没有意义
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > target) {
                // target在左半部分,更新右边界
                // 因为右边界是开区间,所以right = mid,mid位置不会被包含
                right = mid;
            } else {
                // target在右半部分,更新左边界
                // 因为左边界是闭区间,所以left = mid + 1
                left = mid + 1;
            }
        }
        return -1;
    }
};
  1. 27. 移除元素

依然是双指针法,值得注意的一点就是我一开始将等于val的值都换到后面,这样也能AC,不过这样得到的数组会改变元素的相对位置,换到前面就不会

AC代码:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
	//换到后面
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            if (nums[i] == val) {
                swap(nums[i], nums[n - 1]);
                i--;
                n--;
            }
        }
        return n;
    }
};

//双指针法,换到前面
//没有改变元素的相对位置
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};
  1. 977. 有序数组的平方

注意一下全是负数的情况

AC代码:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        int under = -1;
        vector<int> ans(n);
        int pos = 0;
        for (int i = 0; i < n; ++i) {
            if (nums[i] < 0) { // 存在负数,找到最大的负数位置
                under++;
            } else {
                // 存在负数且负数的平方小于当前i位置正数的平方,继续看下一个负数
                while (under != -1 &&
                        nums[under] * nums[under] < nums[i] * nums[i]) {
                    ans[pos] = nums[under] * nums[under];
                    under--;
                    pos++;
                }
                ans[pos] = nums[i] * nums[i];
                pos++;
            }
        }

        //全是负数的情况
        while (under != -1) {
            ans[pos] = nums[under] * nums[under];
            under--;
            pos++;
        }

        return ans;
    }
};