代码随想录算法训练营第一天 | 704. 二分查找、27. 移除元素

本文详细介绍了C++中的数组操作,包括在排序数组中查找元素的第一和最后一个位置、使用二分查找法进行搜索插入位置以及移除元素的方法。通过实例展示了左闭右开和左闭右闭区间的选择及其在代码实现中的应用。
摘要由CSDN通过智能技术生成

目录

数组相关知识

704.二分查找

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

    35.搜索插入位置

27.移除元素

今日收获


数组相关知识

  • 数组是存放在连续内存空间上的相同类型数据的集合
  • 在删除或者增添元素的时候,需要依次移动其他元素的地址
  • C++ vector
    //定义变量类型为int的容器nums
    vector<int>& nums
    
    //获得容器内元素个数
    nums.size()

704.二分查找

题目 704.二分查找

文档 代码随想录-二分法

视频 二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili

状态 可以自己做出来,但思路比较模糊;学完后有清楚的逻辑

  1. 初始思路:在一个升序排列且无重复值的数组中查找目标值,适合使用二分查找。定义左侧边界和右侧边界。多次迭代,每次迭代时取当前的中间元素,如果等于目标值则返回中间元素的下标,大于目标值则重设右边界,小于目标值则重设左边界,直至找到目标元素。

  2. 重点:分清使用的是左闭右开还是左闭右闭。

    左闭右开左闭右闭
    区间取值[low,high)[low,high]
    初始值high = nums.size()high = nums.size()-1
    迭代停止条件low<=highlow<high
    更新右边界high = midhigh = mid-1

    当使用左闭右开时,low=high无意义,因为[low,high)没有取值。即当迭代到low=high时还未返回,说明无法取到目标值

  3. 代码

  • 左闭右闭写法
    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int low = 0, high = nums.size()-1;
            while(low<=high)
            {
                int mid = low + (high-low)/2;
                if(nums[mid]==target) return mid;
                else if(nums[mid]<target)
                    low = mid+1;
                else
                    high = mid-1;
            }
            return -1;
    
        }
    };
  • 左闭右开写法
    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int low = 0, high = nums.size();
            while(low<high)
            {
                int mid = low + (high-low)/2;
                if(nums[mid]==target) return mid;
                else if(nums[mid]<target)
                    low = mid+1;
                else
                    high = mid;
            }
            return -1;
    
        }
    };

    写成 int mid = low + (high-low)/2; 可以防止(high+low>2147483647)超限


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

1.思路:两次二分查找,分别寻找开始位置和结束位置,注意当nums[mid]==target时与简单的查找的区别。

2.代码

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int low1=0,low2=0, high1=nums.size()-1,high2=nums.size()-1;
        int left=-1,right=-1;
        while(low1<=high1){
            int mid = (low1+high1)/2;
            if(nums[mid]==target&&(mid==0?1:(nums[mid-1]<nums[mid]))) {
                left=mid;
                break;
                }
            else if(nums[mid]>target) high1 = mid-1;
            else if(nums[mid]<target) low1 = mid+1;
            else high1 = mid-1;
        }

        while(low2<=high2){
            int mid = (high2+low2)/2;
            if(nums[mid]==target&&(mid==nums.size()-1?1:(nums[mid+1]>nums[mid]))){
              right = mid;
              break;
            }
            else if(nums[mid]>target) high2 = mid-1;
            else if(nums[mid]<target) low2 = mid+1;
            else low2 = mid+1;
        }
     return {left,right};

    }
};

35.搜索插入位置

1.思路:使用左闭右闭的二分查找,存在时返回找到的下标值,不存在时返回迭代结束后的low值,即待插入位置。

2.代码

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

        return low;

    }
};

27.移除元素

题目 27.移除元素

文档 代码随想录

视频 数组中移除元素并不容易! | LeetCode:27. 移除元素_哔哩哔哩_bilibili

状态 自己能写暴力写法;掌握了双指针法

1.初始思路:暴力求解,可以使用双循环,外层循环找等于val的元素下标,内层循环从找到的下标开始调整后边的元素地址,时间复杂度为O(n2)

2.重点:使用双指针法求解。

   - 慢指针slowIndex:指向数组下次更新位置

   - 快指针fastIndex:寻找新数组应有的元素(即不等于val的元素)

一次循环。依次用快指针找到需要保留的元素,并覆盖至慢指针指向的位置,O(n)

3.代码

暴力求解

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len = nums.size();
        int index = 0;
        while(index<len)
        {
            if(nums[index]!=val) index++;
            else{
                len--;
                for(int j = index;j<nums.size()-1;j++)
                    nums[j]=nums[j+1];
            }
        }
        return len;

    }
};

双指针法

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for(int fastIndex = 0; fastIndex < nums.size(); fastIndex++)
        {
            if(nums[fastIndex]!=val){
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
};

今日收获

逐步掌握知识的过程!一个好的开始...

第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值