前言
每日文案:
假如,生活让你迷失了方向,不要迷茫,不要彷徨。早上醒来,睁开眼睛,看到我给你发的信息,它捎去我轻轻的祝福,为你增添生活的勇气,为你点燃每一天的热情,希望你每天都精彩,每步都平安,每刻都快乐!
一、二分查找
题目描述:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目来源:
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) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
题目来源:
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; }
总结
今天是学习算法的第一天,写得不好的地方,请多指教~