一、第一天| 704. 二分查找、27. 移除元素。

文章介绍了数组的基础理论,包括其内存连续性、下标从0开始以及元素不能直接删除等特性。接着讨论了二分查找算法在有序数组中的应用,提供了C++实现,并指出在有重复元素时二分查找的限制。最后,文章展示了如何使用双指针法原地移除数组中指定值的元素。
摘要由CSDN通过智能技术生成

数组基础理论

数组是存放在连续内存空间上的相同类型数据的集合。

  • 数组下标都是从0开始的。

  • 数组内存空间的地址是连续的

正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。

数组的元素是不能删的,只能覆盖。

所以可以看出在C++中二维数组在地址空间上是连续的

704. 二分查找


力扣题目链接(opens new window)

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

这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。

写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。

  1. 对于左闭右闭即[left, right]的写法,需要考虑左右都是可以获取的情况

对于二分法这里while(left<=right)是有效的,因为可以取到right的值,所以left==right是有意义的

对于if (nums[middle] > target) 因为对于中间值,已经大于目标值了,所以对于middle不需要取了,直接更新right=middle-1就可以了。

c语言写法如下:

int search(int* nums, int numsSize, int target){
    int l = 0;  //左区间从0开始
    int r = numsSize -1;//因为数组是从0开始的,所以最右边的值是长度-1
    while(l <= r) //进行判断 当l 小于r的时候一直循环,且还会有l=r的情况
    {
        int mid = (l+r)/2;//更新中间值
        if(nums[mid] > target) //比目标值大更新r
        {
            r = mid - 1;

        }
        else if(nums[mid] < target)//比目标值小更新l
        {
            l = mid + 1;
        }
        else
        {
            return mid; //如果不属于上述两种情况就是找到目标值,之间返回下表mid
        }

    }
    return -1;//当上述循环退出还没找到则返回-1
}
  1. 闭右开即[left, right)

这种写法就是不取最右边的值,直接选取长度就可以了,对于左边写法同上,但是对于右边的话,因为最右边的值是不可选取的。

int search(int* nums, int numsSize, int target){
    int l = 0; //左边值
    int r = numsSize ; //因为数组是从0开始的,所以长度的位置是不可选取的
    while(l < r)  //所以这里的话l是不能等于r的
    {
        //int mid = (l+r)/2;//这里对于直接l+r的话可能会存在大于int范围出现溢出,所以改为下面的最好
        int mid = l +( (r - l)/2);//这里经过简单的数学运算,l+(r/2-l/2)=r/2+l/2=(r+l)/2,但是这样的话就很好的避免了溢出,没有l+r。
        if(nums[mid] > target)  //对于
        {
            r = mid ;

        }
        else if(nums[mid] < target)
        {
            l = mid +1;
        }
        else
        {
            return mid;
        }

    }
    return -1;
}

27. 移除元素


力扣题目链接

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

要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。

双指针法

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组

  • 慢指针:指向更新 新数组下标的位置

主要就是两个指针,快指针进行判断,慢指针存储元素

int removeElement(int* nums, int numsSize, int val){

    int q = 0, p = 0;
    for(p; p < numsSize; p++)
    {
        if(nums[p] != val)
        {
            nums[q] = nums[p];
            q++;
        }
    }
    return q;
}

上述代码例子讲解:

对于数组nums[4]={3 2 2 3} val =3

最开始定义q和p都为0指向位置 q[0] = p[0] = 3

下面开始进入for循环,for循环中只有一个判断p【0】不等于val,这里p的值等于val,所以p向前移动,q不动,因为q的位置需要用不等于val的值来覆盖,当p【1】的时候,p【1】等于2不等于val的时候,这时候q就需要移动了,用p的值来更新q的值,同时q往后移动等待下一次更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值