【LeetCode】十、二分查找法:寻找峰值 + 二维矩阵的搜索

news2024/11/19 16:28:01

文章目录

  • 1、二分查找法 Binary Search
  • 2、leetcode704:二分查找
  • 3、leetcode35:搜索插入位置
  • 4、leetcode162:寻找峰值
  • 5、leetcode74:搜索二维矩阵

1、二分查找法 Binary Search

找一个数,有序的情况下,直接遍历找,时间复杂度为O(n),用二分法,一半一半的砍着找,则时间复杂度为O(log n),更优

在这里插入图片描述

核心:左、中、右三个指针的移动

2、leetcode704:二分查找

在这里插入图片描述

注意下面对中间指针的求法,不写 (l + r ) / 2,写成 l + (r - l) / 2,二者通分后值一样,但l + r可能超出int的最大值,后者这种写法则可规避这个问题。且 除二可以改为位运算 >> 1,其快于除法运算,注意右移的运算优先级很低,要加括号(a + b >> c 会首先执行加法 a + b,然后将结果右移 c 位

public class P704 {

    public static int binarySearch(int[] array, int value) {
        if (array == null || array.length == 0) {
            return 0;
        }
        int left = 0;
        int right = array.length - 1;
        int mid;
        while (left <= right) {
            mid = left + (right - left) / 2;
            if (array[mid] > value) {
                // 右边半截不要了
                right = mid - 1;
            } else if (array[mid] < value) {
                // 左边半截不要了
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

测试:

public class P704 {
    public static void main(String[] args) {
        int[] num = {-1, 0, 3, 5, 9, 12};
        System.out.println(binarySearch(num, 9));
        System.out.println(binarySearch(num, 10));
    }

}

在这里插入图片描述

3、leetcode35:搜索插入位置

在这里插入图片描述
第一个想法是:先普通的二分查找value,返回-1后,说明不存在,那就再遍历这个数组,用双指针,当p1的值 < value && p2的值 > value时,return p1 + 1,但这样应该是复杂了

在这里插入图片描述

换个想法,只需调整下普通的二分查找:这题要求找值target,有就返回下标索引,无就返回插入后的下标索引,因此,这题要找第一个大于等于target的值的下标索引,如果有等于target的,那返回其下标,如果不存在,那就要插入到第一个比target大的值的位置,第一个大的值的下标则往后移动一位。

在这里插入图片描述

public class P35 {
    
    public static int searchOrInsert(int[] array, int target) {
        if (array == null || array.length == 0) {
            return 0;
        }
        int left = 0;
        int right = array.length - 1;
        int ans = array.length;
        while (left <= right) {
            int mid = ((right - left) >> 1) + left;
            if (target == array[mid]) {
                // 如果有,直接返回
                return mid;
            } else if (target < array[mid]) {
                // 如果mid大于target,存一下mid的值
                // 此时mid是大于target的值,但不一定是第一个大于target的值
                ans = mid;
                right = mid - 1;
            } else {
                // 左指针右移,说明target很大,极限时,插入到末尾,此时return array.length即末尾
                left = mid + 1;
            }
        }
        return ans;
    }
}

4、leetcode162:寻找峰值

在这里插入图片描述

一头一尾是负无穷,所以,即使是1,2,3,4这个输入,也有峰值:4

在这里插入图片描述

m+1 > m时,m+1到right之间一定有一个峰值,不论m的左侧是单增、单减、波浪起伏。此时可把左指针移动到m+1的位置,减少搜索范围。

public class P162 {

    public static int getPeak(int[] array) {
        if (null == array || array.length == 0){
            return -1;
        }
        int left = 0;
        int right = array.length - 1;
        // 这儿不能允许left==right,否则当left=right=末尾元素时,mid也就是末尾元素,mid+1就越界了
        while (left < right) {
            int mid = left + ((right - left) >> 1);
            //说明mid和mid+1两个点,从左到右是下降的,mid自身或者mid的左边可能有峰值
            if (array[mid] > array[mid + 1]) {
                right = mid;
            } else {
                // 一定有个峰值出现在mid+1到right之间
                left = mid + 1;
            }
        }
        return left;
    }
}

5、leetcode74:搜索二维矩阵

如题,这样特点的矩阵,本身就是递增的,如图中的1、3、5、7、10、11、16……

在这里插入图片描述

在有序的集合里找一个数字,可以二分查找。但现在虽然有序,却不是集合,是一个二维数组,那把矩阵拍平后就是一个简单的二分查找了。把这个矩阵(二维数组)拍平有两种思路:

  • 直接遍历二维数组,把每个元素装入一位数组,但这样得两层for,时间复杂度太高
  • 思想上拍平,将二维数组的索引,和一维数组建立联系

考虑将二维数组的索引(x,y)转为一维的索引i,。关于二维索引和一维索引的相互转换,发现:

在这里插入图片描述
将二维索引(x,y)和一维索引 i 标出来,得出:一维索引的坐标 i = x * 列总数 + y

如上面总列数为4(0,0)对应的一维坐标正好是 0 * 4 + 0 = 0

如此,不用遍历二维数组,就可将矩阵的每个数都对应一个一维坐标。二分法时,起始左指针 = 0, 右指针 = 行数 × 列数 - 1(即总元素数),计算出mid后,无法根据mid索引在二维数组中取值,需要将一维坐标再倒回去,x = i / 列总数 ,y = i % 总列数

public class P74 {

    public boolean matrixSearch(int[][] matrix, int target) {
        if (null == matrix || matrix.length == 0) {
            return false;
        }
        // 行数
        int row = matrix.length;
        // 列数
        int col = matrix[0].length;
        // 左右指针起始位置
        int left = 0;
        int right = row * col - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            // 无法根据一维的mid索引在二维数组中取值,需要将一维坐标再倒回去
            // x = i / 列总数 ,y = i % 总列数
            int element = matrix[mid / col][mid % col];
            if (target == element) {
                return true;
            } else if (target < element) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }

        }
        return false;
    }
}

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

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

相关文章

国产压缩包工具——JlmPackCore SDK说明(三)——JlmPack_Unpack函数说明

一、JlmPack_Unpack函数说明 JlmPack_Unpack函数是解压jlm文件的核心函数&#xff0c;但是在加密状态下&#xff0c;必须有正确的密码才能解密&#xff0c;该函数具有一定的权限管控条件&#xff0c;部分也需要开发者通过上层系统进行控制。库函数名&#xff1a; JLMPACK_API …

做了个三相电量采集器开源出来,可以方便监测家里用电情况

做了个三相电能采集器&#xff0c;可以测3相的电流、电压、功率、功率因数、用电量&#xff0c;数据上传到HomeAssistant&#xff0c;方便观察家里用电量和实时用电功率。 使用3个pzem004t电参数传感器测量&#xff0c;通过串口与ESP32-C3通信&#xff0c;然后通过WiFi上传至H…

WordPress网站如何做超级菜单(Mega Menu)?

大多数的网站菜单都是像以下这种条状的形式&#xff1a; 这种形式的是比较中规中矩的&#xff0c;大多数网站都在用的。当然还有另外一种菜单的表现形式&#xff0c;我们通常叫做“超级菜单”简称Mega Menu。网站的超级菜单&#xff08;Mega Menu&#xff09;是一种扩展的菜单&…

使用ElementUI组件库

引入ElementUI组件库 1.安装插件 npm i element-ui -S 2.引入组件库 import ElementUI from element-ui; 3.引入全部样式 import element-ui/lib/theme-chalk/index.css; 4.使用 Vue.use(ElementUI); 5.在官网寻找所需样式 饿了么组件官网 我这里以button为例 6.在组件中使用…

数组-移除元素

移除元素 移除元素&#xff08;leetcode27&#xff09; var removeElement function(nums, val) {const n nums.length;let left 0;for (let right 0; right < n; right) {if (nums[right] ! val) {nums[left] nums[right];left;}}return left; };删除有序数组中的重复…

GPT-4o不仅能写代码,还能自查Bug,程序员替代进程再进一步!

目录 1 CriticGPT 01 综合性&#xff08;Comprehensiveness&#xff09;&#xff1a; 02 幻觉问题&#xff08;Hallucinates a problem&#xff09;&#xff1a; 2 其他 CriticGPT 案例 随着人工智能&#xff08;AI&#xff09;技术不断进步&#xff0c;AI在编程领域的应用…

hive中cast()函数

CAST函数用于将某种数据类型的表达式显式转换为另一种数据类型。CAST()函数的参数是一个表达式&#xff0c;它包括用AS关键字分隔的源值和目标数据类型。 语法&#xff1a;CAST (expression AS data_type) expression&#xff1a;任何有效的SQServer表达式。 AS&#xff1a;用…

ATFX汇市:欧元区CPI与失业率数据同时发布,欧元或迎剧烈波动

ATFX汇市&#xff1a;CPI数据是中央银行决策货币政策的主要依据&#xff0c;失业率数据是中央银行判断劳动力市场健康状况的核心指标。欧元区的CPI和失业率数据将在今日17:00同时发布&#xff0c;在欧央行6月6日降息一次的背景下&#xff0c;两项数据将显著影响国际市场对欧央行…

2024 年江西省研究生数学建模竞赛题目 A题交通信号灯管理---完整文章分享(仅供学习)

问题&#xff1a; 交通信号灯是指挥车辆通行的重要标志&#xff0c;由红灯、绿灯、黄灯组成。红灯停、绿灯行&#xff0c;而黄灯则起到警示作用。交通信号灯分为机动车信号灯、非机动车信号灯、人行横道信号 灯、方向指示灯等。一般情况下&#xff0c;十字路口有东西向和南北向…

HR人才测评,如何考察想象力?

什么是想象力&#xff1f; 想象力是指&#xff0c;人们通过在已有物质的基础上&#xff0c;通过大脑想象、加工、创造出新事物的能力&#xff0c;举一个非常简单的例子&#xff0c;在提到鸟这种生活的时候&#xff0c;大家会联想到各种各样不同鸟的品种。 在企业招聘中常常应…

3.1 数据结构-线性表

上午10-12分的选择题&#xff0c;下午15分的大题 大纲 线性结构 顺序存储和链式存储区别 单链表的插入和删除 真题 线性结构 - 栈和队列 真题 串

实现WebSocket聊天室功能

实现WebSocket聊天室功能 什么是WebSocket&#xff1f;WebSocket的工作原理服务器端实现客户端实现 在现代Web开发中&#xff0c;实时通信已经变得越来越重要。传统的HTTP协议由于其无状态和单向通信的特点&#xff0c;无法很好地满足实时通信的需求。而WebSocket协议则应运而生…

【java计算机毕设】仓库管理系统 MySQL springboot vue3 Maven 项目源码代码

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】仓库管理系统MySQL springboot vue3 Maven小组项目设计源代码 2项目介绍 系统功能&#xff1a; vue3仓库管理系统&#xff0c;主要功能包含&#xff1a;个人信息管理&#xff0c;仓库管理&#xff0c;员工…

【你也能从零基础学会网站开发】理解DBMS数据库管理系统架构,从用户到数据到底经历了什么

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 其实前面我们也…

300关卡成语释义典故题库ACCESS\EXCEL数据库

成语典故指关于成语产生、形成、流传的故事传说。成语有很大一部分是从古代相承沿用下来的&#xff0c;它既代表了一个故事典故&#xff0c;又是一种现成的话&#xff0c;很多又有比喻引申意义而被广泛引用。 今天又获得了一个成语游戏的数据&#xff0c;即根据成语典故或者释…

CID引流电商:助力传统电商突破重围实现持续增长

摘要&#xff1a;面临流量成本攀升和市场份额被挤压的挑战&#xff0c;传统电商急需突破重围。CID引流电商通过跨平台引流和精准定位&#xff0c;助力商家实现持续增长&#xff0c;丰富营销手段&#xff0c;创新商业模式。CID引流电商为传统电商的长远发展注入新动力。 在电商…

TFD那智机器人仿真离线程序文本转换为现场机器人程序

TFD式样那智机器人离线程序通过Process Simulation、DELMIA等仿真软件为载体给机器人出离线&#xff0c;下载下来的文本程序&#xff0c;现场机器人一般是无法导入及识别出来的。那么就需要TFD on Desk TFD控制器来进行转换&#xff0c;才能导入现场机器人读取程序。 导入的文…

Lesson 45 The boss‘s letter

Lesson 45 The boss’s letter 词汇 can 能够 n. 罐&#xff0c;听 用法&#xff1a;1. 情态动词&#xff1a;can 动词原形    例句&#xff1a;我能跑。       I can run.    2. a can of … 一罐……    例句&#xff1a;我要一罐可乐。       I wan…

全平台7合一自定义小程序源码系统功能强大 前后端分离 带完整的安装代码包以及搭建教程

系统概述 这款全平台 7 合一自定义小程序源码系统是专为满足各种业务需求而设计的。它整合了多种功能&#xff0c;能够在不同平台上运行&#xff0c;为用户提供了全方位的体验。无论你是企业主、开发者还是创业者&#xff0c;这款系统都能为你提供强大的支持。 代码示例 系统…

手写一个类似@RequestParam的注解(用来接收请求体的参数)

一、本文解决的痛点 按照大众认为的开发规范&#xff0c;一般post类型的请求参数应该传在请求body里面。但是我们有些post接口只需要传入一个字段&#xff0c;我们接受这种参数就得像下面这样单独创建一个类&#xff0c;类中再添加要传入的基本类型字段&#xff0c;配合Reques…