tomoebzk

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

代码随想录Day1

Leetcode 704

本题十分明确指出二分法实现O(log n)的时间复杂度,根据区间选区的不同,二分法有两种不同的写法

  1. 左闭右闭

    int left=0,right=nums.size()-1;
            while(left<=right)
            {
                int mid=left+(right-left)/2;//防止越界
                if(nums[mid]<target)
                    left=mid+1;
                else 
                    right=mid-1;
            }
    return left
    

    left是最后得到的位置,根据题目要求通常需要判断边界条件以及二分法结果是否满足题目要求,例如704题中的target

    if(left==nums.size())return -1;
            if(nums[left]==target)return left;
            else return -1;
    
  2. 左闭右开

    int left=0,right=nums.size();
    
            while(left<right)
            {
                int mid=left+(right-left)/2;
                if(nums[mid]<target)//正确答案位于[mid+1,right)
                    left=mid+1;
                else right=mid;//正确答案位于[left,mid)区间
                
            }
    
            if(right==nums.size()||nums[right]!=target)return -1;
            else return right;
    

    代码随想录中针对mid的计算采用了移位运算,采用了二进制左移相当于除以2,速度更快

    int middle = left + ((right - left) >> 1);
    

Leetcode 27

image-20260114152035764

说人话就是把所有非val的元素全部放到nums的前面,由于形参传入的是&nums,因此需要直接对nums进行操作,采用双指针进行,slowIndex负责维护新排列,fastIndex负责遍历原排列。灵神把双指针归类进入滑动窗口,将[leftIndex,rightIndex]作为一个可变的滑动窗口,根据rightIndex的遍历以及题目条件不断更新leftIndex的位置,停止条件就是rightIndex遍历完整个vector容器。

class Solution {
public:
    //同向双指针
    int removeElement(vector<int>& nums, int val) {
        int slowIndex=0,fastIndex=0;
        for(;fastIndex<nums.size();fastIndex++)
        {
            if(nums[fastIndex]!=val)
                nums[slowIndex++]=nums[fastIndex];
        }
        return slowIndex;
    }
};

Leetcode 977

image-20260114152800879

本题想多了,一直在考虑能不能只遍历一遍并且不申请额外空间,但是想了很久没有思路,最后看到题解直接申请了新的空间进行反向双指针

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        std::vector<int>ans(nums.size(),0);
        int left=0,right=nums.size()-1;
        int index=ans.size()-1;
        while(left<=right)
        {
            if(abs(nums[left])<=nums[right])
            {
                ans[index]=pow(nums[right],2);
                index--;
                right--;
            }
            else
            {
                ans[index]=pow(nums[left],2);
                index--;
                left++;
            }
        }
        return ans;
    }
};

其实看到题的第一反应就是直接暴力计算然后ranges::sort排序,但是这样就没了锻炼双指针的意义。

Leetcode 34

该题就是明确二分法得到不同的结果区间,毕竟不是所有题目都需要正好相等,例如第一个小于target的元素、第一个大于target的元素、target出现的区间等等。

类似于c++ranges::lower_bound、ranges::upper_bound

≥target第一个元素下标 lowerbound(nums,target)
>target第一个元素下标 lowerbound(nums,target+1)
<target的最后一个元素下标 lowerbound(nums,target)-1
≤target的最后一个元素下标 lowerbound(nums,target+1)-1

ranges::lower_bound得到的就是前几道题的left,ranges::upper_bound返回的lowerbound(nums,target+1)

是否使用ranges库函数取决于当前题目的目标,如果只是其中一步使用了二分法,采用ranges库函数无可厚非,但是如果就是考察二分法就不适合直接写ranges的库函数

posted on 2026-01-14 16:54  broderk  阅读(9)  评论(0)    收藏  举报