代码随想录算法训练营第一天| 704. 二分查找、35.搜索插入位置、27. 移除元素

刷题的第一天,从头开始学习。只要学习都是收获。

题目704

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

在这里插入图片描述

题目链接:https://leetcode.cn/problems/binary-search/
文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715

思路

本题是使用二分法来解题。因为没学过数据结构,所以根本没听说过二分法。
首先想到的就是使用循环去遍历数组中的每一个元素,判断是否与目标值相等。相等的话就输出下表,否则返回-1。

二分查找法

先去学习了一下什么是二分法。

使用二分法的前提:
1、数组为有序数组
2、数组中无重复元素

二分查找法的过程可以简单描述为如下过程:
1、使用了while循环和for循环。将目标元素和查找范围的中间值做比较(如果目标元素=中间值,查找结束),将目标元素分到较大/或者较小的一组。
2、通过分组,可以将查找范围缩小一半。
3、重复第三步,直到目标元素=新的范围的中间值,查找结束。

相关内容的学习参考了如下的链接: https://blog.csdn.net/iLoyo_/article/details/131491911

解答

根据区间的不同,结果可以分为两种情况

第一种是区间左闭右闭

class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        int left = 0;
        int right = nums.size() - 1; // 这个地方要减去1
        while (left <= right) // 当left==right,区间[left, right]依然有效,所以用 <=
        { 
            int middle = (right - left) / 2;//注意这一句,一定要写在while循环里面,因为每一次都要更新middle的值
            if (nums[middle] > target) 
            {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } 
            else if (nums[middle] < target) 
            {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } 
            else 
                return middle; // 数组中找到目标值,直接返回下标
            
        }
        return -1;//不存在返回-1
    }
};

第二种是左闭右开

class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        int left = 0;
        int right = nums.size(); //right不能在区间内,不用减去1
        while (left < right) // left == right的时候,[left, right)是无效的空间,所以使用 <
        { 
            int middle = (right - left) / 2;
            if (nums[middle] > target) 
            {
                right = middle; // target 在左区间,在[left, middle)中
            } 
            else if (nums[middle] < target) 
            {
                left = middle + 1; // target 在右区间,在[middle + 1, right)中
            } 
            else 
            { 
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        return -1;
    }
};

二分法从原理上来理解不难,容易写错的地方就是区间的问题。要注意。

补充(太久没看了,都是自己忘得很基础的知识呀)

在这里插入图片描述

c++只会有一个返回值

题目35

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

在这里插入图片描述

题目链接:https://leetcode.cn/problems/search-insert-position/
文章讲解:
https://programmercarl.com/0035.%E6%90%9C%E7%B4%A2%E6%8F%92%E5%85%A5%E4%BD%8D%E7%BD%AE.html#%E6%80%9D%E8%B7%AF

思路

学习了704后,看到了有序、无重复的数组,就想到了使用二分法
很顺利的就写出了代码
但在最后写返回按顺序插入的位置的时候,没明白怎么写才好
看了讲解之后,发现最后是返回left或者right+1,一开始还不明白为什么会这样写。
后来画图看了看才明白
在这里插入图片描述

解题

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) 
    {
        int left = 0;
        int right = nums.size() - 1;
        while(left <= right)
        {
            int middle = (left+right)/2;
            if(nums[middle] > target)
            {
                right = middle - 1;
            }
            else if(nums[middle] < target)
            {
                left = middle +1; 
            }
            else
                return middle;
        }
        //left>right跳出了循环
        return right+1;

    }
};

题目27

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

在这里插入图片描述

题目链接:https://leetcode.cn/problems/remove-element/
文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html
视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP

思路

看到这道题的第一时间,想到的就是对数组进行循环遍历,判断数组中的每一个元素是否与目标值相等,然后将不相等的元素都取出来构成新的数组。
但是题目不能用另外一个新数组
后面有想到用不重复的元素去覆盖重复的元素
因为要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖

解答

有两种方法

第一种暴力求解,具体实现过程和思路中描述的差不多
是把数组中与目标数相同的元素给覆盖掉

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

            }
        }
        return len;

    }
};

第二种使用了双指针
是把数组中与目标数不同的元素取出来构成新的数组

真的是一种很妙的方法

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

双指针法使用了两个指针——一个快指针和一个慢指针

快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置

一定要搞清楚这两个指针的定义才能看懂解题过程

今日总结

今天是练习的第一天。

对于c++来说,自己已经很久没有写过了,平时连看的都不多。之前也只跟着书本学过一遍,只敲过案例,很多基础语法也都忘了。后面一点一点的学习。只要学习了就有收获。

  • 34
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了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、付费专栏及课程。

余额充值