首页 > 其他分享 >day 1 数组 704.二分查找、27.移除元素

day 1 数组 704.二分查找、27.移除元素

时间:2023-10-10 12:12:44浏览次数:44  
标签:27 target nums 704 middle int right 移除 left

704.二分查找

题目链接:704.二分查找

视频教程

文章教程

思路

利用 middle 去寻找 target

  • 前提条件:

    这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,二分查找法返回的元素下标可能就不唯一,这些都是二分法的前提,以后看到题目描述后可以先想一想是否符合二分查找的条件。

  • 难点:

    二分查找的难点在于边界问题,很容易思路混乱。例如到底是 while(left <= right) 还是 while(left < right),到底是 right = middle - 1 还是 right = middle 呢?

  • 解决方式:

    二分法的区间一般有两种定义方式,左闭右闭即 [left, right] ,左闭右开即 [left, right)

第一种:左闭右闭

区间的定义就决定了二分法的代码应该怎么写,因为定义 target 在 [left, right] 区间,所以有如下两点:

  • while (left <= right) 要使用 <= ,因为 left = right 是有意义的,例如 [1, 1]
  • if(nums[middle] > target) right 要赋值为 middle - 1 ,最初 right 的赋值为 nums.length - 1,因为当前这个 nums[middle] 一定不是 target ,那么接下来要查找的区间右结束下表一定是 middle - 1

代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1; // 定义target在左闭右闭区间里,[left, right]
        while (left <= right) {
            int middle = left + (right - left) / 2; // 防止边界溢出
            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; // 找到target,直接返回下标
            }
        }
        return -1; // 没有找到target,返回-1
    }
}

第二种:左闭右开

边界处理方式截然不同,如下两点:

  • while(left < right) ,这里使用 < ,因为 left == right 在区间 [left, right) 是没有意义的。例如 [1, 1) ,这是违法的。
  • if(nums[middle]) right 更新为 middle ,最初 right 的赋值为 nums.length ,因为当前 nums[middle] 不等于 target ,而 寻找区间又恰为 左闭右开 区间,所以 right 更新为 middle ,下一个查询区间也不会去比较 nums[right]

代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length; // 定义target在左闭右闭区间里,[left, right)
        while (left < right) {
            int middle = left + (right - left) / 2; // 防止边界溢出
            if (nums[middle] > target) {
                right = middle; // 在左区间里,所以 [left, middle)
            } else if (nums[middle] < target) {
                left = middle + 1; // 在右区间里,所以 [middle, right)
            } else {
                return middle; // 找到target,返回
            }
        }
        return -1;,// 未找到target,返回-1
    }
}

27.移除元素

题目链接:27.移除元素

视频教程

文章教程

思路

不需要考虑数组中超出新长度后面的元素。

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

双指针法

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

定义快慢指针:

  • 快指针:寻找新元素的指针,通过遍历数组寻找出不含目标元素的数组
  • 满指针:用来在原数组的基础上生成新数组

双指针法在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针。

代码实现

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
class Solution {
    public int removeElement(int[] nums, int val) { //同侧开始
        int slow = 0;
        for (int fast = 0;fast < nums.length;fast++) {
            if (nums[fast] != val) {
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }
}
class Solution {
    public int removeElement(int[] nums, int val) { //两侧开始
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            if (nums[left] == val) {
                nums[left] = nums[right];
                right--;
            } else {
                left++;
            }
        }
        return left;
    }
}

标签:27,target,nums,704,middle,int,right,移除,left
From: https://www.cnblogs.com/bobochicken/p/17754337.html

相关文章

  • 力扣-2744-最大字符串配对数目
    给你一个下标从0开始的数组words,数组中包含互不相同的字符串。如果字符串words[i]与字符串words[j]满足以下条件,我们称它们可以匹配:字符串words[i]等于words[j]的反转字符串。0<=i<j<words.length请你返回数组words中的最大匹配数目。注意,每个字符串最......
  • redis cluster增加和移除主从节点【转】
    Redis-Cluster集群之Cluster节点增减上篇我们了解了Redis的cluster集群的搭建,现在我们来说一下cluster集群的节点的增减集群增加主节点1.新建一个7006的一个节点,让其作为一个新的主节点加入,在/redis-cluster目录下,新建一个7006目录,配置相应的配置文件和数据目录,启动7006这个节......
  • poj2279
    Mr.Young'sPicturePermutationsTimeLimit:1000MS MemoryLimit:65536KTotalSubmissions:5841 Accepted:1860DescriptionMr.Youngwishestotakeapictureofhisclass.Thestudentswillstandinrowswitheachrownolongerthanth......
  • 2023-2024-1 20231327 司宏林 《计算机基础与程序设计》第2周学习总结
    学期(如2023-2024-1)学号(如:20231300)《计算机基础与程序设计》第X周学习总结作业信息这个作业属于哪个课程<班级的链接>(2022-2023-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(https://edu.cnblogs.com/campus/besti/2023-2024-1-CFAP/homework/12998......
  • ORA-27301: OS failure message: No buffer space available
    这个报错主要这是由于网络缓冲区预留的可用空间较少。可以通过调整参数min_free_kbytes设置,这个参数要设置到总内存的0.4%以下,比如 256GBRAM,vm.min_free_kbytes设置1073742,可以设置更小。numa模式的参考OracleLinux:ORA-27301:OSFailureMessage:NoBufferSpaceAvai......
  • FastAPI学习-27 使用@app.api_route() 设置多种请求方式
    对同一个访问函数设置多个http请求方式api_route使用使用methods参数设置请求方式fromfastapiimportFastAPIapp=FastAPI()@app.api_route('/demo/b',methods=['get','post'])asyncdefdemo2():return{"msg":"demo2su......
  • css移除button按钮的所有属性
    例如需要点击按钮才能触发的事件,按钮里面放图片会影响原本样式,这时需要隐藏button的样式style="all:unset;"效果:点击客服图标打开小程序客服窗口 ......
  • 力扣-2427-公因子的数目
    给你两个正整数a和b,返回a和b的公因子的数目。如果x可以同时整除a和b,则认为x是a和b的一个公因子。 示例1:输入:a=12,b=6输出:4解释:12和6的公因子是1、2、3、6。示例2:输入:a=25,b=30输出:2解释:25和30的公因子是1、5。提示:1<=a,......
  • 为什么减去这两个纪元毫秒值(在1927年)会得到一个奇怪的结果?
    内容来自DOChttps://q.houxu6.top/?s=为什么减去这两个纪元毫秒值(在1927年)会得到一个奇怪的结果?在Java中,Date对象的getTime()方法返回的是从1970年1月1日00:00:00GMT开始的毫秒数。当你解析日期字符串时,这些毫秒数是基于GMT的。然而,你的程序运行的环境时区是Asia/Shanghai,其......
  • 202310061227-《心得:低版本mysql配置一,些轮子插件》
    1.对于mysql5.7.42,驱动(connector)选择:5.1.46。2.测试链接时:useSSL=true&enabledTLSProtocols=TLSv1.1 驱动链接字符串上要拼接上。3.驱动链接字符串:高版本mysql,意味着高版本connector,选>=8;低版本,选择5.x;               高版本mysql,com.my......