代码随想录算法训练营第一天|704.二分查找、27.移除元素、977.有序数组的平方

一、leetcode704.二分查找

题目链接:https://leetcode.cn/problems/binary-search/

1.左闭右闭

由于之前跟着王道系统地学过一遍并有笔记,在快速回顾笔记之后就立马做题了。

​ 上来不到十分钟就把代码写好了,结果运行不了,开始自我怀疑。又看了一下,发现 mid = (low + high) / 2中的括号没加,改玩之后就能正常运行了,真是太粗心了。

int search(vector<int>& nums, int target) {
        int low = 0, high = nums.size() , mid;
        mid = (low + high)/2;
        while(low <= high)
        {
            if(nums[mid]==target)
            return mid;
            else if(nums[mid]<target)
            {
                low = mid + 1;
                mid = (low + high)/2;
            }
            else if(nums[mid]>target)
            {
                high = mid - 1;
                mid = (low + high)/2;
            }
        }
        return -1;
    }

2.左闭右开

左闭右开的解法如下:

int search(vector<int>& nums, int target) {
        int low = 0, high = nums.size() , mid;
        mid = (low + high)/2;
        while(low < high)
        {
            if(nums[mid]==target)
            return mid;
            else if(nums[mid]<target)
            {
                low = mid + 1;
                mid = (low + high)/2;
            }
            else if(nums[mid]>target)
            {
                high = mid;
                mid = (low + high)/2;
            }
        }
        return -1;
    }

左闭右开的不同点就是high指向的是原来的后一个元素,即:
1.在初始时high = nums.size();
2.在过程中,high = mid;

但是对于while循环的判断条件,我还是有疑问的,不确定加不加等号。在看完讲解之后,我意识到了:

左闭右开的本质就是在[low,high)这个区间内折半查找,所以low = high是没有意义的

。由此我也明白了为什么要令high = mid:

此时要mid的左边折半查找,由于右开又要求包含mid左边所有的元素所以此时只有让high =
mid才能成立。用卡哥的话说,重点还是对区间定义的理解。

二、leetcode27.移除元素

题目链接:https://leetcode.cn/problems/remove-element/

1.暴力(失败)

上来我先按提示用暴力解法解了一遍,代码如下:

int removeElement(vector<int>& nums, int val) {int k = 0;for(int i =0;i<nums.size();i++){if(nums[i] != val)
​       k++;}
​    vector<int> arr(nums.size(),0);int j = 0;for(int i = 0;i <nums.size();i++){if(nums[i] != val){
​        arr[j] = nums[i];
​        j++;}}for(int i = 0;i < arr.size();i++){
​      nums[i] = arr[i];}return k;
  }

虽说是暴力,但是时间复杂度为O(n),空间复杂度也为O(n),借助了一个辅助数组。可惜并不能正确运行,而且我也找不到原因,哭死…

2.双指针法

看完卡哥介绍双指针法(快慢指针法)的视频和文字之后,实现的代码如下:

int removeElement(vector<int>& nums, int val) {
       int slow = 0;
       for(int fast = 0 ; fast < nums.size() ; fast++)
       {
        if(nums[fast] != val)
        {
            nums[slow] = nums[fast];
            slow++;
        }
       }
       return slow;
    }

这里的快指针的作用是来选择我们真正需要的元素,即不等于val的元素。

慢指针的作用是把选择好的元素依次放入新数组中(是同一个数组,但位置不同)

直观表现为:在相同时间内,fast指针从0扫到最后一个与元素,而slow指针从0扫到第k个元素

fast指针更像是去探索、判断,而slow指针更像是去接收探索、判断的结果

三、leetcode977.有序数组的平方

题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/

1.暴力

卡哥说这题要用双指针法,但我实在没想到怎么去用…太菜),只想了暴力解法的思路,代码如下:

 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;
  }

时间复杂度为O(nlogn)

2.双指针法

与其说是双指针,不如说是三指针法。在原数组上有两个指针,分别指向数组的起始和结尾。由于实在没办法在原数组上动刀,只能牺牲一下空间,另外设置一个数组来接收最后的结果。
代码如下:

vector<int> sortedSquares(vector<int>& nums) {
        int i = 0,j = nums.size() - 1,k=nums.size() - 1;
        vector<int> result(nums.size(),0);
        while(i <= j)
        {
            if(nums[j]*nums[j] >= nums[i]*nums[i])
            {
                result[k] = nums[j]*nums[j];
                k--;
                j--;
            }else
            {
                result[k] = nums[i]*nums[i];
                k--;
                i++;
            }
        }
        return result;
    }

就和卡哥说的一样,数组的最大值只可能出现在两端,而且越往中间数字越小。于是分别依次对比首尾元素,可得到有序序列。

因为是先求最大值,然后依次往小了求,所以辅助数组的指针是从最后一个元素开始的,这与我们的惯性思维不同。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值