算法题总结(一)——二分查找专题

news2025/1/6 19:55:50

二分查找

我们二分查找的本质就是每次能够通过中间值来进行分割,能够比较判断,查找到或者接近需要的数据,然后把一部分的数据丢弃掉。

原题

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

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

左闭右闭:

class Solution {
    public int search(int[] nums, int target) {
        // 避免当 target 小于nums[0]  大于nums[nums.length - 1]时多次循环运算
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;
        }
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);  //分割点
            if (nums[mid] == target)
                return mid;
            else if (nums[mid] < target)  //丢弃一部分
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;
        }
        return -1;
    }
}

35.搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

我们使用二分法查不存在的数据时,最后left就是应该插入的位置!

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] == target)
                return mid;
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;

            return left;// 最终的left返回了应该插入的位置


        }
    }

34.在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]

//左右指针移动,先用二分法找到一个位置,然后左右移动判断

class Solution {
    public int[] searchRange(int[] nums, int target) {

        int[] result ={-1,-1};
        int index=binarySearch(nums,target);
        if(index==-1)
            return result;
        int left=index;
        int right=index;
        while(left-1>=0 && nums[left-1]==nums[index])
        {
            left--;
        }
        while(right+1<nums.length && nums[right+1]==nums[index])
        {
            right++;
        }
        result[0]=left;
        result[1]=right;
        return result;
    }

    public int binarySearch(int[] nums,int target)
    {
        int l=0;
        int r=nums.length-1;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if(nums[mid]==target)
            {
                return mid;
            }
            else if(nums[mid]<target)
            {
                l=mid+1;
            }
            else if(nums[mid]>target)
            {
                r=mid-1;
            }
        }
        return -1;
    } 
}

69.X的平方根

给你一个非负整数 x ,计算并返回 x 的 算术平方根

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

使用二分法查找符合条件的元素

即找到一个平方比x小的 最大的一个就行

即使用二分查找的方法 在0-x之间找到一个符合的最大元素,由于是找一个符合的最大的元素,因此当小于号的时候,l=mid+1,即往右边去查找。

使用long进行类型转换是因为x的平方根相乘可能无法用int表示。

class Solution {
    public int mySqrt(int x) {  //二分方法通用思想
        int l=0;
        int r=x;
        int ans=-1;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if((long)mid*mid<=x)  //既满足ans=mid的条件,又满足l=mid+1的条件。
            {
                ans=mid;
                l=mid+1;
            }
            else{
                r=mid-1;
            }

        }
        return ans;
    }
}

367.有效的完全平方数

给你一个正整数 num 。如果 num 是一个完全平方数,则返回 true ,否则返回 false 。

完全平方数 是一个可以写成某个整数的平方的整数。换句话说,它可以写成某个整数和自身的乘积。

不能使用任何内置的库函数,如 sqrt 。

示例 1:

输入:num = 16
输出:true
解释:返回 true ,因为 4 * 4 = 16 且 4 是一个整数。

示例 2:

输入:num = 14
输出:false
解释:返回 false ,因为 3.742 * 3.742 = 14 但 3.742 不是一个整数。
class Solution {
    public boolean isPerfectSquare(int num) { //二分查找从0-num中间的数
        int left = 0;
        int right =num;

        while(left<=right)
        {
            int mid=left+(right-left)/2;
            if((long)mid*mid==num)
                return true; 
            else if((long)mid*mid>num)   //分割
                right=mid-1;   //注意不要写成 right-1
            else if((long)mid*mid<num)
                left = mid + 1;

        }
        return false;

    }
}

74、搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵:

  • 每行中的整数从左到右按非严格递增顺序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。

示例 1:

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

和上面平方根那个题目一样,相当于不是精确的找,只是找到比target小的 最大的一个就行

按照行查找的时候,不需要一定相等,只需要找到比target小的 最大的一个就行。

class Solution {
    //两次二分查找,先搜索合适的行,再在这一行中搜索列。
    public boolean searchMatrix(int[][] matrix, int target) {
        int index=search1(matrix,target);
        if(index==-1)   
            return false;
        return search2(matrix[index],target);
    }

    public int search1(int[][] matrix,int target)
    {
        int low=0;
        int high=matrix.length-1;
        int ans=-1;   //和上面平方根那个题目一样,相当于不是精确的找,只是找到比target小的 最大的一个就行
        while(low<=high)
        {
            int mid=low+(high-low)/2;
            if(matrix[mid][0]<=target)
            {   
                ans=mid;  //记录
                low=mid+1;  //分割缩小范围

            }
            else{
                high=mid-1;
            }
        }
        return ans;
    }

    public boolean search2(int[] row,int target)
    {
        int left=0;
        int right=row.length-1;
        while(left<=right)
        {
            int mid=left+(right-left)/2;
            if(row[mid]==target)    
                return true;
            else if(row[mid]>target)
                right=mid-1;
            else if(row[mid]<target)
                left=mid+1;
        }
        return false;
    }
}

33、搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4

旋转数组使用中间值被分成有序和无序两部分,这样利用有序比较大小,就可以判断target的具体位置。

我们二分查找的本质就是每次能够通过中间值来进行分割,能够比较判断,查找到或者接近需要的数据,然后把一部分的数据丢弃掉。

class Solution {
    //分为有序数组和旋转数组
    public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length-1;
        while(left<=right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]==target)
                return mid;
            //注意此时用小于等于,因为mid可能和left相等
            //左边的有序
            if(nums[left]<=nums[mid])
            {
                //target在前半部分
                if(target>=nums[left] &&target<nums[mid])
                    right=mid-1;
                else
                    left=mid+1;
            }
            else  //后半部分有序
            {
                //且target在后半部分
                if(target<=nums[right]&&target>nums[mid])
                    left=mid+1;
                else
                    right=mid-1;
            }

        }
        return -1;
    }
}

153、寻找旋转排序数组中的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], …, a[n-1]]旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

右旋,上一题是左旋。

示例 1:

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。

示例 2:

输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。

其实左旋右旋本质上都是一样的:我们可以模仿上一题,利用mid来分割数组,如果nums[left]<=nums[mid],说明mid左边是有序的,所以左边的最小值就是nums[left],否则,mid的右边就是有序的,那么mid的右边部分nums[mid]就是最小值。

即我们二分查找的本质就是每次能够通过判断分割,能够查找到或者接近需要的数据,然后把一部分的数据丢弃掉。

class Solution {
    public int findMin(int[] nums) {
        //模仿第33题的思路,数组被分为有序和无序两个数组
        int left=0;
        int right=nums.length-1;
        int ans=nums[0];
        while(left<=right)
        {
            int mid=left+(right-left)/2;
            //mid左边是有序的,知道mid左边是有序的,那么我们可以记录下来左边的最小值,然后就可以吧左边的丢弃了
            if(nums[left]<=nums[mid])
            {
                ans=Math.min(ans,nums[left]);  //记录
                left=mid+1;  //丢弃左边的
            }
            //mid右边是有序的
            else
            {
                ans=Math.min(ans,nums[mid]);
                right=mid-1;
            }
        }
        return ans;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2143416.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LabVIEW提高开发效率技巧----使用快捷键

在LabVIEW的开发过程中&#xff0c;熟练掌握和运用快捷键可以极大地提升工作效率&#xff0c;减少重复性操作所花费的时间。快捷键不仅可以加快编程速度&#xff0c;还能让开发者更加专注于逻辑实现和功能设计。细问问将详细介绍LabVIEW中的常用快捷键&#xff0c;特别是强大的…

101012分页属性

4k页面 P&#xff08;有效位&#xff09;&#xff1a;1有效&#xff0c;0无效 R/W&#xff08;读写位&#xff09;&#xff1a;1可读可写&#xff0c;0可读 U/S&#xff08;权限位&#xff09;&#xff1a;1(User)&#xff0c;0(System) A&#xff08;物理页访问位&#xff…

医学数据分析实训 项目五 聚类分析--蛋白质消费结构分析--车辆驾驶行为指标

文章目录 项目五&#xff1a;聚类分析实践目的实践平台实践内容任务一&#xff1a;蛋白质消费结构分析步骤 任务一&#xff1a;蛋白质消费结构分析数据预处理&#xff08;四&#xff09;模型建立及优化KMeans 任务二 车辆驾驶行为&#xff08;四&#xff09;模型建立及优化 项目…

并发带来的对象一致性问题

多线程操作带来数据不一致情况分析&#xff0c;简单demo。 public class Object_IS {private Student_Object so new Student_Object("张三", 123);public static void main(String[] args) throws InterruptedException {Object_IS os new Object_IS();os.test1(…

论文笔记:交替单模态适应的多模态表征学习

整理了CVPR2024 Multimodal Representation Learning by Alternating Unimodal Adaptation&#xff09;论文的阅读笔记 背景MLA框架实验Q1 与之前的方法相比&#xff0c;MLA能否克服模态懒惰并提高多模态学习性能?Q2 MLA在面临模式缺失的挑战时表现如何?Q3 所有模块是否可以有…

输电线路缺陷检测数据集(绝缘子自爆,破损,闪络,鸟巢,防震锤脱落五种缺陷)

输电线路数据集&#xff08;绝缘子自爆&#xff0c;破损&#xff0c;闪络&#xff0c;鸟巢&#xff0c;防震锤脱落五种缺陷&#xff09;包括&#xff1a; 1.绝缘子自爆 2.绝缘子破损绝、闪络 3.鸟巢 4.防震锤脱落 数据增强后的数量 对应数量&#xff1a;1828&#xff0c;1467&a…

类加载器详细介绍

类加载器我们要聊一个神秘而又重要的角色——Java类加载器。这家伙&#xff0c;就像是个超级英雄&#xff0c;总是在关键时刻挺身而出&#xff0c;为我们的Java程序提供强大的支持。我会尽量用简单易懂的方式来介绍它。 一 、类加载器介绍 1、类加载器是什么&#xff1f; 想象…

高频率快响应信号隔离变送器

隔离变送器相册: 隔离变送器图片----捷晟达科技​​​​ 隔离变送器---深圳捷晟达科技 隔离变送器---捷晟达科技 高频率快响应信号隔离变送器 定义&#xff1a; 高频率是指隔离变送器从输入到输出采样时的时间&#xff0c;该产品响应频率从10KHz~100KHz&#xff0c;产品精度高&…

【CSS】选择器(基础选择器、复合选择器、属性匹配选择器、结构伪类选择器、伪元素选择器)

选择器 引入方式基础选择器复合选择器属性匹配选择器结构伪类选择器伪元素选择器 引入方式 1&#xff1a;外联 <!-- css引入方式1&#xff1a;外联 外联与内嵌优先级相同&#xff0c;取决于加载顺序 --><link rel"stylesheet" type"text/css" h…

箭头检测系统源码分享

箭头检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

子查询优化

MySQL学习大纲 我的数据库学习大纲 1、什么是子查询&#xff1a; 1.MySQL 从 4.1 版本开始支持子查询&#xff0c;使用子查询可以进行 SELECT 语句的嵌套查询&#xff0c;即一个 SELECT 查询的结果作为另一个 SELECT 语句的条件。子查询可以一次性完成很多逻辑上需要多个步骤才…

二分+构造,CF 1063C - Dwarves, Hats and Extrasensory Abilities

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1063C - Dwarves, Hats and Extrasensory Abilities 二、解题报告 1、思路…

AtCoder ABC370 A-D题解

比赛链接:ABC370 AT 上 400 分寄。 Problem A: Code #include <bits/stdc.h> using namespace std; int main(){int L,R;cin>>L>>R;if(LR)cout<<"Invalid"<<endl;else if(L1)cout<<"YES"<<endl;elsecout<…

【数据结构】经典题

所以&#xff0c;语句 x; 的语句频度为&#xff1a;n(n1)(n2&#xff09;/6 选C 临时变量 t&#xff1a;只使用了一个额外的变量来存储交换的值。 没有使用额外的数组&#xff1a;所有的操作都是在原数组 a 上进行的。 因此&#xff0c;算法的空间复杂度是常数级别的&#xff0…

定位HardFault

一、HardFault定义 STM32出现HardFault_Handler硬件错误的原因主要有两个方面&#xff1a; 1、内存溢出或者访问越界。&#xff08;包括使用野指针&#xff09; 2、堆栈溢出。 二、定位HardFault步骤 1. 判断所使用堆栈&#xff1a; 发生异常之后可首先查看LR寄存器中的值…

十五,Spring Boot 整合连接数据库(详细配置)

十五&#xff0c;Spring Boot 整合连接数据库(详细配置) 文章目录 十五&#xff0c;Spring Boot 整合连接数据库(详细配置)最后&#xff1a; JDBC HikariDataSource(Spring Boot内置的数据库) HikariDataSource: 目前市面上非常优秀的数据源&#xff0c;是 Spring Boot2默认数…

gcc/g++的使用:

目录 (1). 程序的翻译过程 预处理&#xff1a; gcc -E 源文件 编译&#xff1a; gcc -S 源文件 汇编&#xff1a;gcc -c 源文件 连接&#xff1a; (2) 语言的自举(也叫 编译器的自举)&#xff1a; (3). 查看可执行程序在连接时依赖的库: ldd 可执行程序的名字 。 (4). …

C语言 | Leetcode C语言题解之第414题第三大的数

题目&#xff1a; 题解&#xff1a; int cmp(const void *a, const void *b) {return *(int*)a < *(int*)b; }int thirdMax(int* nums, int numsSize){qsort(nums, numsSize, sizeof(nums[0]), cmp);int diff 0;for (int i 1; i < numsSize; i) {if (nums[i] ! nums[i…

体感魂斗罗-开篇

文章目录 前言新的目标Flag 前言 黑神话悟空大火&#xff0c;9月14&#xff0c;周鸿祎在抖音平台分享了360团队用两天的业余时间将《黑神话&#xff1a;悟空》爆改为体感游戏的过程&#xff0c;通过身体动作来控制游戏中的角色&#xff0c;实现更加自然和直观的操作方式。 把…

【秋招笔试-支持在线评测】8.28华为秋招(已改编)-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 华为专栏传送🚪 -> 🧷华为春秋招笔试 目前今年秋招的笔…