刷题01:二分查找与双指针的应用

71 阅读1分钟

二分查找(Binary Search)

二分查找是一种在有序数组中快速查找目标值的算法,时间复杂度为 O(log n),空间复杂度为 O(1)。

典型题目: 704. 二分查找

题目要点:

  1. 数组是有序的(一定单调性)
  2. 使用双指针(left和right)定义搜索范围
  3. 每次比较中间元素(mid)与目标值,缩小搜索范围

实现

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) { // [left, right]左闭右闭区间
            int mid = left + (right - left) / 2; // 防止溢出
            if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
};

注意点:

  • 循环条件left <= right对应的是左闭右闭区间 
  • 计算mid时使用left + (right - left)/2而非(left+right)/2,防止整数溢出 
  • 更新指针时要±1,确保范围能不断缩小

双指针技巧(Two Pointers)

双指针技巧通常用于原地修改数组或在单次遍历中解决问题,时间复杂度通常为O(n),无需构建额外空间所以空间复杂度一般O(1)。  

典型题目

27. 移除元素

题目要点

原地修改数组(避免额外空间)则可以考虑使用双指针:

  • fast指针遍历原数组

  • slow指针构建新数组,直接在原数组上覆盖,无需额外空间。

实现

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //fast遍历数组,slow指向新数组
        int fast=0, slow=0;
        for(; fast<nums.size(); fast++){
            if(val != nums[fast]){
                nums[slow++] = nums[fast];
            }
            //相等的话fast快指针继续遍历,slow则不动
        }
        return slow;
    }
};

时间复杂度

  • 时间复杂度:O(n),仅需一次遍历。 
  • 空间复杂度:O(1)

977. 有序数组的平方

要点

  • 单调性(包含负数)且平方后的极值分布:平方后的最大值肯定是在数组的俩端(要么最左的负数,要么最右边的正数)所以可以考虑使用双指针由俩边向中间遍历。

  • 要求新数组,所以可以定义一个vector

实现

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        vector<int> result;
        result.resize(n);
        //left,right分别指向原数组的俩端,双指针从俩端向中间遍历
        //newIndex指向新数组的末尾,由后往前填充数组
        int left=0, right=n-1, newIndex=n-1;
        while(left<=right){
            int rSquares = nums[right]*nums[right];
            int lSquares = nums[left]*nums[left];
            if(rSquares>=lSquares){
                result[newIndex--] = rSquares;
                right--;
            }else{
                result[newIndex--] = lSquares; 
                left++;
            }
        }
        return result;
    }
};

复杂度

  • 时间复杂度:O(n),仅需一次遍历。
  • 空间复杂度:O(n),存储结果数组(题目允许返回新数组)。