LeetCode算法刷题


前言

本文将分享自己学习二分查找和移除元素的经验


一、LeetCode704二分查找

接下来我先写出二分的常用的模板,考虑到整数二分的情况比较复杂,所以接下来只列举整数二分,这又会分为两种情况,总的可以概括为:数组区间为左闭右闭和左闭右开。

划重点:模板还是很重要的,一定要记住,多背过几遍

1.左闭右闭代码如下

//区间划[l,r]划分为[l,mid]和[mid + 1,r]时使用
int sreach(int l,int r)
{
    while(l <= r)
    {
        int mid = (l + r)>>1;//如果害怕越界可以改成 l + (l-r)>>1;
        if(check(mid)) r = mid-1;//check()判断mid是否满足性质,目标在左半部分的话修改右边界,否则修改左边界
        else l= mid + 1;
    }
}

2.左闭右开代码如下

//区间划[l,r]划分为[l,mid]和[mid + 1,r]时使用
int sreach(int l,int r)
{
    while(l < r)
    {
        int mid = (l + r)>>1;
        if(check(mid)) r = mid;//check()判断mid是否满足性质,目标在左班部分的话修改右边界,否则修改左边界,因为mid值已经被访问,而该方法又取不到右边界,而之后又要用到递归,所以要这样写
        else = mid + 1;
    }
}

二、LeetCode704

思路:1.看左闭右闭还是左闭又开的情况。
2.分辨出我们要用到的check()方法的具体含义
3.套模板
4.题目的额外要求

分析:1.本题目为左闭右闭的情况.
2.check()方法的具体表示为nums[mid]与target的大小的比较.
3.套模板.
4.题目额外要求为没查到时返回-1.

1.Java

代码如下

class Solution {
    public int search(int[] nums, int target) {
    //这里的 l 和 f自己进行初始化
    int left = 0;
    int right = nums.length -1;
    //模板,情形为左闭右闭。判断条件check()是和目标值比较大小。
    while(left <= right) {
        int mid = (left + right)>>1;
        if(nums[mid]==target)
            return mid;
        else if(nums[mid] > target)
            right = mid-1;
        else
            left = mid +1;
    }
    return -1;
    }
}

2.C++

代码如下

class Solution {
public:
    int search(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() -1;
    //模板开始,左闭又闭,check类型:比较大小,nums[mid]和target的关系
    while(left <= right) {
        int mid = (left + right)>>1;
        if(nums[mid]==target)
            return mid;
        else if(nums[mid] > target)
            right = mid-1;
        else
            left = mid +1;
    }
    return -1;
    }
};

这里其实JAVA和C+++其实并没有特别大的区别。要注意JAVA中int right = nums.length -1;和C++中的int right = nums.size() -1;的不同。其它的思想是一致。

总结且思考:二分不只是可以查找一些数,它本质是对一些性质的筛选。在LeetCode702中,它代表的性质刚好就是数字大小的性质。实际上,其他性质也同样适用于二分查找,从而我们也可以得出一个结论:二分查找不一定需要有单调性,没有单调性也同样可以用二分

三.LeetCode 27.移除元素

1.简单介绍:双指针法最大的用处使用来优化,原来的暴力解法两个for循环的时间复杂度是O(n平方),利用双指针可以缩小到O(n).所以思考时,我可能可以先考虑写出暴力解法,然后寻找 i 和 j 的线性关系。随后在进行优化处理

对于本题目,我们双指针一先一后,先指针fast用来记录新数组将要获得的元素,而后指针slow用来记录新数组元素将要存放的地址:
思路:1.遍历,找出需要移除的元素位置。**替换:从数组的后面寻找元素替换。1)当前数组最后一个元素仍需要移除则更新数组元素后继续前移。2)当最后一个数组不需要移除,那就进行替换
2.更新数组的长度,继续遍历

以下是一个双指针的小模板
双指针小模板

2.Java

代码如下

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for(int fast = 0;fast < nums.length - 1;fast++){
            if(nums[fast] != val){//不需要删除的情况.更新数组
                nums[slow] = nums[fast];//快指针用来获取新获得的元素,慢指针用来获取新数组中的地址
                slow++;//位置同样往后移动
            }
        }
        return slow;
    }
}

3.C++

代码如下

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
int slow = 0;
        for(int fast = 0;fast < nums.size() - 1;fast++){
            if(nums[fast] != val){//不需要删除的情况.更新数组
                nums[slow] = nums[fast];//快指针用来获取新获得的元素,慢指针用来获取新数组中的地址
                slow++;//位置同样往后移动
            }
        }
        return slow;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值