Day01| 704.二分查找、27.移除元素、977.有序数组的平方

2025-07-09

704.二分查找

题目链接:704.二分查找
文档讲解:代码随想录
状态:解决,重新理解二分法

思路

最开始了解的二分查找法,竟只是闭区间的一种,没想到还有这么多说法

讨论其根本数学逻辑,是落在集合中,若为闭区间查找left/right=mid±1是核心思想,必须把查找过的全部剔除,不然查找过的数据仍然在集合中可能出错,就一定会出错;若为开区间,什么是开区间?落在算法中可以设置左、右虚节点代表(全是花活),此时left/right=mid核心思想。

开区间和闭区间的区别本质还体现在终止条件中,一想便知。

谨记二分法使用的严格条件:有序不重复

闭区间图解:

chart

开区间图解:

chart

题解

class Solution {
public:
    int search(vector<int>& nums, int target) 
    {//最常用的版本闭区间
        // int left = 0,right = nums.size()-1;
        // while(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;
    //学习的左闭右开版本--有区间的概念,虚节点
        // int left = 0,right = nums.size();
        // while(left<right)
        // {
        //     int mid = left+(right-left)/2;
        //     if(nums[mid]>target){right = mid;}
        //     else if(nums[mid]<target){left = mid+1;}
        //     else return mid;
        // }
        // return -1;
    //全部开区间
        int left = -1,right = nums.size();
        while(left+1<right)
        {
            int mid = left+(right-left)/2;
            if(nums[mid]>target){right = mid;}
            else if(nums[mid]<target){left = mid;}
            else return mid;
        }
        return -1;
    }
};

27.移除元素

题目链接:27.移除元素
文档讲解:代码随想录
状态:暴力解决、学习了双指针(数组复用)法

思路

最开始的思路:两个for循环,把有用的元素放到前面,无用的放到后面,虽然能解决问题,但不像正规军队。

暴力解法:题目最本质的要求是?是移除数组中的元素,而显而易见数组中的元素无法删除,只能整体移动覆盖且size-1,解法由此得来。

chart

双指针(数组复用)解法:fast负责不断向后寻找需要数据并赋值给slow位置,slow不断向前构成新数组

chart

题解

class Solution {
public:
    int removeElement(vector<int>& nums, int val) 
    {//我的方法
        // int number = 0;
        // for(int i = 0;i<nums.size();i++)
        // {
        //     if(nums[i] == val)
        //     {
        //         for(int j = nums.size()-1;j>=0;j--)
        //         {
        //             if(nums[j]!=val)
        //             {
        //                 nums[i] = nums[j];
        //                 nums[j] = val;
        //                 number++;
        //                 break;
        //             }
        //             if(i==j) 
        //             {
        //                 return number;
        //             }
        //         }
        //     }
        //     else number++;
        // }
        // return number;
    //暴力覆盖法
        // int number = nums.size();
        // for(int i = 0;i<number;i++)
        // {
        //     if(nums[i] == val)
        //     {
        //         for(int j = i+1;j<number;j++)
        //         {
        //             nums[j-1] = nums[j];
        //         }
        //         i--;
        //         number--;
        //     }
        // }
        // return number;
    //双指针,新数组法
        int fast = 0, slow = 0;
        for(fast = 0;fast<nums.size();fast++)
        {
            if(nums[fast]!=val)
            {
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }
};

977.有序数组的平方

题目链接:977.有序数组的平方
文档讲解:代码随想录
状态:瞟了眼思路轻松解决

思路

最开始的思路:全部平方,再排个序,美滋滋啊,但是不懂排序这个题目就失去了意义。

双指针法:本题的双指针和上一个题性质明显不同,对于有序序列,平方大小一定是两边大中间小,双指针由此得来。

图解:

chart

题解

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) 
    {//暴力思想
        // for(int i = 0;i<nums.size();i++)
        // {
        //     nums[i] *= nums[i];
        // }
        // sort(nums.begin(),nums.end());
        // return nums;
    //双指针法
        int k = nums.size()-1;
        vector<int> result(nums.size(),0);
        for(int i = 0, j = nums.size()-1;i<=j;)
        {
            if(nums[i]*nums[i]>=nums[j]*nums[j]){result[k--] = nums[i]*nums[i];i++;}
            else {result[k--] = nums[j]*nums[j];j--;}
        }
        return result;
    }
};