Day1——数组 二分查找、移除一个数

简介: Day1——数组 二分查找、移除一个数

前言


每日文案:

假如,生活让你迷失了方向,不要迷茫,不要彷徨。早上醒来,睁开眼睛,看到我给你发的信息,它捎去我轻轻的祝福,为你增添生活的勇气,为你点燃每一天的热情,希望你每天都精彩,每步都平安,每刻都快乐!

一、二分查找


题目描述:

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

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/binary-search

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目来源:

704. 二分查找 - 力扣(LeetCode)

1、解法一:直接搜索


我们可以看到传进来的是一个数组,那么我们要搜索一个数,最简单的还是直接搜索。

一个一个遍历搜索:

int search(int* nums, int numsSize, int target){
    for(int i=0;i<numsSize;i++)
    {
        if(*(nums+i)==target)
        {
            return i;
        }
    }
    return -1;
}

思路很简单,就是从头开始搜索,搜索到了就返回 i (数组下标)的值,不然就是-1 。

2、二分查找(重点)


这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件 ——代码随想录

我们一个一个搜太慢了,咱们还记得小时候学过的课文吗:八达岭隧道。对没错就是詹天佑先生主持修建的八达岭隧道,在修隧道时用了一个很精妙的方法:竖井开凿法。大概过程如下:

图片如下:

image.png

我们发现什么?我们多个方向一下相对来挖,就很快可以挖通,那我们在遍历数组的时候也可以借鉴一下,我们从两头往中间靠,是不是快了呢。

代码如下:

int search(int* nums, int numsSize, int target){
    for(int i=0,j=numsSize-1;i<numsSize;i++,j--)    //两边一起开始
    {
        if(j<i)                                    //如果j<i都还没找到,这辈子就这样了,走吧
        break;
        if(*(nums+i)==target)                //谁找到返回水的下标
        return i;
        if(*(nums+j)==target)
        return j;
    }
    return -1;                    //找不到就返回-1
}

核心思想还是两头一起挖,要是想用真的竖井开凿,多管齐下,也可以,原理差不多,大家可以自己实践一下~

二、移除一个数


题目描述:


给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

题目来源:

27. 移除元素 - 力扣(LeetCode)

1、解法一:暴力求解


我们要在数组里面找出一个值,然后把他删掉,但是数组这种结构,它是连续不断的,你删除了一个它就像会空出一个在那里:

如图:

image.png

它会有一个空缺,你填了什么就是什么,我们遍历输出的是时候就会有“垃圾值”,那怎么办呢,我们只能把整个数组前移一位,用后面的数组覆盖前面的,搬运起来,这样就变成了连续的桥了。

如图:

1da1a4c8a8cd4589b3a966a025b046c8.jpeg

这样就把他们连起来了,最后一个空位,理论上还是=4(也就是前一个),因为是粘贴过去的,那里还是会有原本hhhh,但没有关系,根据题目要求,我们把长度减一就好了哇~

int removeElement(int* nums, int numsSize, int val){
    int count=0;
    for(int i=0;i<numsSize;i++)        //开始遍历数组
    {
        if(*(nums+i)==val){                //如果找到了要删除的数
            for(int j=i;j<numsSize-1;j++)    //开始粘贴,搬运
            {
                *(nums+j)=*(nums+j+1);        //前一项=后一项
            }
            numsSize--;                    //长度减一,把最后那个擦除了
            i--;     //这个很重要!!如果没有这个,两个要删除的数重叠了,就会漏一个,           
        }                我们要确保遍历每一个
    }
    return numsSize;
}

2.解法二:双指针


这里我的理解是使用一个快慢指针来完成删除

建议画图来一步一步走,思维会很通透!!

int removeElement(int* nums, int numsSize, int val)
{
        int count=0,w=0,i=0;
        int *slow=nums;
        int *fast=nums;
        for(i=0;i<numsSize;i++)
        {
            if(*(fast+i)!=val)            //快慢指针
            {
                *slow=*(fast+i);        //赋值
                slow++;             //慢指针向前一步
                count++;           //记录次数
            }
        }
        w=numsSize-(i-count);        //计算数组长度
    return w;
}

总结


今天是学习算法的第一天,写得不好的地方,请多指教~

相关文章
|
5天前
|
存储
力扣 合并两个有序数列||移除元素
力扣 合并两个有序数列||移除元素
10 0
|
6天前
|
存储 算法 Java
数据结构和算法面试题:给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
数据结构和算法面试题:给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
45 0
|
6天前
|
算法
leetcode-34:在排序数组中查找元素的第一个和最后一个位置
leetcode-34:在排序数组中查找元素的第一个和最后一个位置
19 0
|
5月前
|
算法 测试技术 C#
C++二分算法:得到山形数组的最少删除次数
C++二分算法:得到山形数组的最少删除次数
|
7月前
|
算法
【算法专题突破】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(17)
【算法专题突破】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(17)
29 0
|
9月前
|
算法
LeetCode-34 在排序数组中查找元素的第一个和最后一个位置
LeetCode-34 在排序数组中查找元素的第一个和最后一个位置
|
10月前
|
算法 C语言 C++
【二分查找】34. 在排序数组中查找元素的第一个和最后一个位置
二分查找是一种高效的查找算法,其时间复杂度为 O(log n)。在许多情况下,我们需要在一个有序数组中找到某个目标值的搜索范围。本文将介绍一种基于二分查找的搜索范围查找算法,该算法能够快速找到目标值在数组中的起始和结束位置。
48 0
|
11月前
|
存储
返回集合中最大,最小的元素,再将元素进行排序
返回集合中最大,最小的元素,再将元素进行排序
49 0
|
11月前
|
人工智能
求数组满足条件个数
求数组满足条件个数
62 0
|
算法
力扣34题. 在排序数组中查找元素的第一个和最后一个位置
力扣34题. 在排序数组中查找元素的第一个和最后一个位置
69 0