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

学习算法的第一天

目录

学习算法的第一天

前言

一、二分查找

1、解法一:直接搜索

2、二分查找(重点)

二、移除一个数

题目描述:

1、解法一:暴力求解

2.解法二:双指针

总结


前言

每日文案:

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


一、二分查找

题目描述:

给定一个 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、二分查找(重点)

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

                                                                                                                        ——代码随想录

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

图片如下:

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

代码如下:

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、解法一:暴力求解

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

如图:

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

如图:

 这样就把他们连起来了,最后一个空位,理论上还是=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;
}

总结

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

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值