当前位置: 首页 > article >正文

[代码随想录算法01] 704. 二分查找、27. 移除元素、977有序数组的平方

前言

 数组相关的最常用的操作的就是二分,因为二分可以很明显的将O(N)的时间复杂度降到O(logN),所以在一些中等的题目里面,我们很容易看到进阶的操作里面有优化时间复杂度的做法。

下一个常见的操作就是双指针,双指针对于有序的数组处理问题就是一绝,他可以通过,两个指针的快慢不同,直接将O(N^2)的暴力枚举,直接降低成O(2N),也就是两次遍历即可。

题目链接

1、LeetCode704.二分查找
2、LeetCode27.移除元素
3、LeetCode977.有序数组的平方

 一、二分查找

 思路:常见的二分总共有三种写法,对应的就是闭区间左闭右开开区间。见下代码

分别对应的while的条件是不一样的,在rangs库函数里面的实现也是不一样的,这个我们可以在C++20里面的文档里面查看,库函数的使用方法是直接使用rangs里的lower_bound函数就是二分,tips:笔面不建议直接使用库函数,因为因为这个题就是让咱写二分的实现思路,哈哈哈。

class Solution {
public:
//闭区间
    int search1(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1,mid=0;
        while(left<=right){
            mid=left+((right-left)>>1);
            if(nums[mid]<target)left=mid+1;
            else if(nums[mid]>target)right=mid-1;
            else return mid;
        }
        return -1;
    }
//左闭右开
    int search2(vector<int>& nums, int target) {
        int left=0,right=nums.size(),mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(nums[mid]<target)left=mid+1;
            else if(nums[mid]>target)right=mid;
            else return mid;
        }
        return -1;
    }
//开区间
    int search3(vector<int>& nums, int target) {
        int left=-1,right=nums.size(),mid=0;
        while(left+1<right){
            mid=left+((right-left)>>1);
            if(nums[mid]<target)left=mid;
            else if(nums[mid]>target)right=mid;
            else return mid;
        }
        return -1;
    }
//库函数
    int search(vector<int>& nums, int target) {
        auto i=ranges::lower_bound(nums,target)-nums.begin();
        if(nums[i]==target)return i;
        else return -1;
    }
};

二、移除元素

 思路1:暴力枚举,内层循环移动后续元素的位置。

思路2:快慢指针,遇见不等于目标元素的慢的++

思路3:库函数,直接erase(nums,val)元素即可。

class Solution {
public:
//暴力枚举
    int removeElement1(vector<int>& nums, int val) {
        int sz=nums.size();
        for(int i=0;i<sz;i++){
            if(nums[i]==val){
                for(int j=i+1;j<sz;j++){
                    nums[j-1]=nums[j];
                }
                i--,sz--;
            }
        }
        return sz;
    }
//快慢指针
    int removeElement2(vector<int>& nums, int val) {
        int slow=0;
        for(int x:nums){//这里的K相当于快指针遍历
            if(x!=val) nums[slow++]=x;
        }
        return slow;
    }
//库函数
    int removeElement(vector<int>& nums, int val) {
        erase(nums,val);
        return nums.size();
    }
};

三、有序数组的平方

 思路:暴力解法,直接范围for相乘,然后sort一下就行。快排的时间复杂度高。

思路2:直接用双端的数进行比较,优化时间复杂度。优化成O(N)。

class Solution {
public:
//暴力解法
    vector<int> sortedSquares1(vector<int>& nums) {
        for(auto& it:nums){
            it*=it;
        }
        sort(nums.begin(),nums.end());
        return nums;
    }
//双指针优化
    vector<int> sortedSquares(vector<int>& nums) {
        int n=nums.size();
        vector<int>res(n);
        int i=0,j=n-1;
        for(int p=n-1;p>=0;p--){
            int x=nums[i],y=nums[j];
            if(-x>y){
                res[p]=x*x;
                i++;
            }else{
                res[p]=y*y;
                j--;
            }
        }
        return res;
    }
};

总结

我们后续的算法基本上前面基础算法的结合体,越刷到后面的题目的时候,所以前面我们的算法思想一定要明白,基础不牢,地动山摇,希望我们在刷算法的路上,一起相伴,早日取得成功!passion!

 


http://www.kler.cn/a/414004.html

相关文章:

  • mfc110u.dll是什么意思,mfc110u.dll丢失解决方法大全详解
  • 【论文复现】YOLOv5复现
  • [极客大挑战 2019]HardSQL--详细解析
  • matlab显示sin二维图
  • JavaScript对象笔记
  • 跟李笑来学美式俚语(Most Common American Idioms): Part 36
  • std::srand(static_cast<unsigned int>(std::time(0)));每一部分都是啥意思
  • 图数据库 Cypher语言
  • 深度解读sparkRDD宽窄依赖
  • C语言main()函数
  • 【C知道】ES6特性
  • 两个生活中的例子反向理解正/反向代理?
  • unity中Rigidbody组件的其他属性和方法
  • 【Kubernetes 集群核心概念:Pod】pod生命周期介绍【五】
  • PHP 生成分享海报
  • 【C++】cin、cout基础编程题:完整解析与优化解法
  • 模拟手机办卡项目(移动大厅)--结合面向对象、JDBC、MYSQL、dao层模式,使用JAVA控制台实现
  • 继承与多态(下)
  • 网络原理->DNS协议和NAT协议解
  • 04-数据结构