算法第一天|二分查找LeetCode704、LeetCode35、LeetCode34、|移除元素LeetCode27、LeetCode26、LeetCode283|有序数组平方LeetCode977

整数二分查找算法思路总结:

        1、整数二分算法一定有解,但是需要检查解是不是所需要的解

        2、整数二分可以分为两种区间范围:

左闭右闭(常用,mid>=target):
    /*定义左区间*/
    l = 0
    /*定义右区间*/
    r = nums.size()-1

左闭右开(mid>target)
    /*定义左区间*/
    l = 0
    /*定义右区间*/
    r = nums.size()

        3、整数二分步骤:

                步骤1:定义左右区间(常用左闭右闭)

int l = 0;
int r = nums.size()-1;

                步骤2:开始循环二分,直到l>=r停下

while(l<r)
{
    ...
}

                 步骤3:在循环中定义中点位置,并进行中点位置与target的判断,更新端点

int l = 0;
int r = nums.size()-1;
while(l<r)
{
    //方式1:
    int mid =(l+r)>>1;
    if(nums[mid]>=target)
    {
        r = mid;
    }
    else
    {
        l = mid+1;
    }
    
}

                         方式1是在当target的位置在mid的左边满足true时使用,比如寻找非递减数组中的某个元素的第一个值的位置,需要满足mid的位置>=第一个值的位置。

                        如果在此时使用mid=(l+r+1)>>1,会出现无限循环,假设[3,3],需要第一个值的位置, mid = (0+1+1)>>1=1;(nums[1]=3)>=(target=3);r=mid=1,与上一次一样,就会无限循环。

int l = 0;
int r = nums.size()-1;
while(l<r)
{
    //方式2:
    int mid =(l+r+1)>>1;
    if(nums[mid]<=target)
    {
        l = mid;
    }
    else
    {
        r = mid-1;
    }
    
}

                        方式2是在当target的位置在mid的右边满足true时使用,比如寻找非递减数组中的某个元素的最后一个值的位置,需要满足mid的位置<=最后一个值的位置。

                        如果在此时使用mid=(l+r)>>1,会出现无限循环,假设[3,3],需要最后值的位置, mid = (0+1)>>1=0;(nums[0]=3)<=(target=3);l=mid=0,与上一次一样,就会无限循环。

LeetCode704 二分查找

题目链接:704.二分查找

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //定义左右下标,使用左闭右闭
        int l=0,r= nums.size()-1;

        //判断什么时候可以找到target
        while(l<r)
        {
            //定义中点位置
            //1、如果中点位置满足nums[mid]>=target返回true时,中点位置使用mid = (l+r)>>1
            //2、如果中点位置满足nums[mid]<=target返回true时,中点位置使用mid = (l+r+1)>>1
            int mid = l+r>>1;
            if(nums[mid]>=target) r = mid;
            else l=mid+1;
        }
        return nums[l]==target?l:-1;
        
    }
};

LeetCode35 搜索插入位置

题目链接:35.搜索插入位置

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        //排序数组,本身满足二分法
        //定义左右闭区间
        int l=0,r=nums.size()-1;

        //如果大于整个数组:
        if(target>*(nums.end()-1))return nums.size();
        //二分循环判断
        while(l<r)
        {
            //定义中点,两种方式都行,这里使用nums[mid]>=target,r= mid
            int mid = l+r>>1;
            if(nums[mid]>=target) r = mid;
            else l=mid+1;

        }
        //4,6找5,l=0,r=1,mid=0,nums[mid]=4<5,触发l =0+1=1,满足要插入的位置
        return nums[l]==target?l:l;
        
    }
};

        问题:

                1、在普通的二分法基础上,增加了另外的判断情况,如果不存在需要返回插入位置,所以就会出现如果target>nums的最大值,需要将其插入到最后。

LeetCode34 在排序数组中查找元素的第一个和最后一个的位置

题目链接:在排序数组中查找元素的第一个和最后一个位置

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        //使用两个二分法,分别查找左右位置
        //左边的起始位置满足:nums[mid]>=target,
        //右边的最终位置满足:nums[mid]<=target

        int l=0,r=nums.size()-1;
        int i=l,j=r,m=l,n=r;
        vector <int>res(2,-1);
        if(!nums.size()) return res;
        while(i<j)
        {
            int mid = (i+j)>>1;
            if(nums[mid]>=target) j = mid;
            else i=mid+1;
        }
        if(nums[i]==target) 
        {
            res[0]=i;
            while(m<n)
            {
                int mid = m+n+1>>1;
                if(nums[mid]<=target) m=mid;
                else n=mid-1;
            }
             res[1]=m;

        }
        return res;
    }
};

         问题:

                1、需要使用两次二分来寻找左右两个值,nums[mid]>=target,可以用于寻找第一个元素,nums[mid]<=target,可以用于寻找最后一个元素

                2、判断当nums.size()==0时的情况

移除数组中的某些元素思路总结:

        1、快慢指针:快慢指针在同一个for循环下工作,慢指针用于记录新的数组,快指针用于遍历数组

        2、左右指针:左右指针向中间逼近,左指针、右指针分别寻找满足自己的条件,然后在满足l<r条件下,swap(左指针,右指针)

LeetCode27 移除元素

题目链接:27、移除元素

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //使用左右指针
        //左指针找到val停下
        //右指针找到不是val的停下
        //左右指针swap
        int left=0,right=nums.size()-1;
        while(left<right)
        {
            while(nums[left]!=val&&left<right) left++;
            while(nums[right]==val&&left<right) right--;
            if(left<right)
            {
                swap(nums[left],nums[right]);
                left++;
                right--;
            } 
        }
        int i=0;
        for(i;i<nums.size();i++)
        {
            if(nums[i]==val) break;
        }
        return i;
    }
};
class Solution {
public:
    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];
        }
        return slow;
    }
};

LeetCode26 删除有序数组中的重复项

题目链接:26、删除有序数组中的重复项

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        //使用快慢指针
        //slow指针记录新数组
        //fast指针遍历全部的数组
        if(!nums.size())return 0;
        int slow=0;
        for(int fast = 0;fast<nums.size();fast++)
        {
            if(nums[fast]!=nums[slow])
            {
                nums[++slow] = nums[fast];
            }
        }
        //最终要的时元素数量,所以要+1
        return slow+1;
        
    }
};

 ​​​​​​LeetCode283 移动0

题目链接:283、移动0

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        //使用快慢指针
        //不易使用左右指针,因为这个题需要保持非零元素的相对顺序
        int slow=0;
        for(int fast=0;fast<nums.size();fast++)
        {
            //如果发现快指针不为0,交换
            if(nums[fast]!=0)
            {
                swap(nums[slow++],nums[fast]);
            }
        }
        
    }
};

  ​​​​LeetCode977 有序数组的平方

题目链接:有序数组的平方

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        //左右指针,向中间逼近  
        //左右相等的时候也要进行填入
        int left=0,right=nums.size()-1;
        vector <int> res;
        while(left<=right)
        {
            if(nums[left]*nums[left]<=nums[right]*nums[right])
            {
                res.push_back(nums[right]*nums[right]);
                right--;
            }
            else
            {
                res.push_back(nums[left]*nums[left]);
                left++;
            }
        }
        //输入的顺序是从大到小,需要reverse
        reverse(res.begin(),res.end());
        return res;
        
    }
};

         思路:

                1、使用双指针,从两边向中间夹进,但是当左右相等的时候,也需要进行填入

                2、首先输入的是最大元素,而题目要求是从小到大,所以需要翻转vector,reverse

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值