【算法练习】leetcode算法题合集之二分查找篇

二分查找

LeetCode69.x的平方根

LeetCode69.x的平方根

只要小于等于就可以满足条件了。

class Solution {
    public int mySqrt(int x) {
        int left = 0, right = x;
        int ans = -1;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            if ((long) mid * mid <= x) {
                ans = mid;
                left = mid + 1;

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

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

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

二分查找获取元素的左边界

左边界是可能不存在的。

当target==nums[mid],继续在左边寻找更合适的mid

寻找大于等于target的元素。如果有等于的元素,是可以返回的。如果有大于的元素,返回的结果是mid+1。

class Solution_LC34 {
    public int[] searchRange(int[] nums, int target) {
        int start = lowerBounds(nums, target);
        if (start == nums.length || nums[start] != target) {
            return new int[]{-1, -1};
        }
        int end = lowerBounds(nums, target + 1) - 1;
        return new int[]{start, end};
    }

    private int lowerBounds(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
}

二维矩阵类

LeetCode74.搜索二维矩阵

LeetCode74.搜索二维矩阵

找到最后一个不大于target的元素。比如[1,10,23],target是3,获取到的元素为1。

等于直接获取low,进行二分的时候获取(high-low+1)/2。存在low=1,high=2,low一直为1的情况。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int rowIndex = binarySearchFirstCol(matrix, target);
        if (rowIndex < 0 || rowIndex >= matrix.length) {
            return false;
        }
        return binarySearchRow(matrix[rowIndex], target);
    }

    private int binarySearchFirstCol(int[][] matrix, int target) {
        int low = -1, high = matrix.length - 1;
        while (low < high) {
            int mid = low + (high -low+1 ) / 2;
            if (matrix[mid][0] > target) {
                high = mid - 1;
            } else {
                low = mid;
            }
        }
        return low;
    }

    private boolean binarySearchRow(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (right - left) / 2 + left;

            if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                return true;
            }
        }
        return false;
    }
}

LeetCode240.搜索二维矩阵II

LeetCode240.搜索二维矩阵II

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        for (int[] nums : matrix) {
            if (binarySearch(nums, target)) {
                return true;
            }
        }
        return false;
    }

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

数组从左下角向右上方向移动,向上是变小,向右是变大。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int i = matrix.length - 1, j = 0;
        while (i >= 0 && j < matrix[0].length) {
            if (matrix[i][j] > target) {
                i--;
            } else if (matrix[i][j] < target) {
                j++;
            } else {
                return true;
            }
        }
        return false;
    }

旋转数组类

LeetCode33.搜索旋转排序数组

寻找中间元素,判断是否找到;mid元素不是目标元素,判断mid元素是否在左升区间,如果在,判断目标元素是否在[left,mid],缩小范围。

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            if (nums[mid] == target) {
                return mid;
            }
            // left到mid之间是有序的。
            if (nums[mid] >= nums[left]) {
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }

            } else {
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }

        }
        return -1;

    }
}

LeetCode153.搜索旋转数组的最小值(**)

LeetCode153.搜索旋转数组的最小值

二分查找我原本以为很简单,但是里面的细节真的很多。

while (left <= right) 的终止条件是left>right,进行left = mid + 1;后nums[left]的性质就改变了。

nums[mid] == nums[left],到底是修改left还是right,数组中存在两个元素,循环第一次获取到的nums[mid] == nums[left],所以要比较第二遍。

class Solution {
    public int findMin(int[] nums) {
        int left = 0, right = nums.length - 1;
        int ans = Integer.MAX_VALUE;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            if (nums[mid] >= nums[left]) {
                ans = Math.min(ans, nums[left]);
                left = mid + 1;
            } else {
                ans = Math.min(ans, nums[mid]);
                right = mid - 1;
            }
        }
        return ans;

    }
}

nums[mid]<nums[right],都意味着mid在右边升序段中。所以最小值在[left,mid]之间。

nums[mid] < nums[right]小于是符合条件的,所以right = mid;大于等于是不符合条件的,所以要 mid + 1

测试用例:数组[2,1],发现2>1, left边界更新,当跳出循环,low变成相对大的元素。

数组升序 left–x 升序 x–right 升序

比较nums[left]还是nums[right],因为nums[right]相对nums[mid]较大。在升序队列[1,2,3,4,5]中,nums[left]是最小的。比nums[left]大,无法判定最小值在[left,mid]还是[mid,right]之间。

class Solution {
    public int findMin(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int mid = (right - left) / 2 + left;
            // 
            if (nums[mid] < nums[right]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return nums[left];
    }
}

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

154. 寻找旋转排序数组中的最小值 II

如果小于最右边元素,说明在最小值在[left,mid]

如果大于最右边元素,说明最小值在[mid,right]

如果等于最右边的元素,无法判断,换下一个元素。

class Solution {
    public int findMin(int[] nums) {
        int left = 0, right = nums.length - 1;

        while (left < right) {
            int mid = (right - left) / 2 + left;
            if (nums[mid] < nums[right]) {
                right = mid;
            } else if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else {
                right = right - 1;
            }
        }
        return nums[left];

    }
}

找极大、极小值

LeetCode162.寻找峰值/极大值

LeetCode162.寻找峰值

判断如果nums[mid] > nums[mid + 1],那么峰值在[left,mid]之间。

如果nums[mid] < nums[mid + 1],峰值在[mid+1,right]之间

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

其他

寻找两个正序数组的中位数(**)

LeetCode4. 寻找两个正序数组的中位数

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int length1 = nums1.length;
        int length2 = nums2.length;
        int total = length1 + length2;
        if (total % 2 == 0) {
            return (getKth(nums1, nums2, total / 2 + 1) + getKth(nums1, nums2, total / 2)) / 2;
        } else {
            return getKth(nums1, nums2, total / 2 + 1);
        }
    }

    private double getKth(int[] nums1, int[] nums2, int k) {
        int length1 = nums1.length;
        int length2 = nums2.length;
        int index1 = 0;

        int index2 = 0;
        while (true) {
            // 边界情况
            if (index1 == length1) {
                return nums2[index2 + k - 1];
            }
            if (index2 == length2) {
                return nums1[index1 + k - 1];
            }
            if (k == 1) {
                return Math.min(nums1[index1], nums2[index2]);
            }
            int i1 = Math.min(nums1.length, k / 2 + index1) - 1;
            int i2 = Math.min(nums2.length, k / 2 + index2) - 1;
            int num1 = nums1[i1];
            int num2 = nums2[i2];
            if (num1 > num2) {
                k -= (i2 - index2 + 1);
                index2 = i2 + 1;
            } else {
                k -= (i1 - index1 + 1);
                index1 = i1 + 1;
            }
        }
    }
}

LeetCode287. 寻找重复数

LeetCode287. 寻找重复数

原地hash修改数组,hash表需要额外空间

如果不允许重复的话,小于等于4的元素个数一定是小于等于4的。因为排序好了的数组4个位置放不下大于4个的元素。

class Solution {
    public int findDuplicate(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int mid = (right - left) / 2 + left;
            int count = 0;
            for (int i = 0; i < nums.length; i++) {
                if (nums[i] <= mid) {
                    count++;
                }
            }
            if (count > mid) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【2024最新-python3小白零基础入门】No4.python控制语句学习

文章目录 1 选择结构1.1 if语句 2 循环结构2.1 while循环语句2.2 for循环语句2.3 break、continue、pass在循环中的用途 对于 Python 程序中的执行语句,默认是按照书写顺序依次执行的,这时称这样的语句是顺序结构的。但是,仅有顺序结构还是不够的,因为有时需要根据特定的情况,有…

2024年【建筑电工(建筑特殊工种)】考试题库及建筑电工(建筑特殊工种)模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 建筑电工(建筑特殊工种)考试题库是安全生产模拟考试一点通总题库中生成的一套建筑电工(建筑特殊工种)模拟考试&#xff0c;安全生产模拟考试一点通上建筑电工(建筑特殊工种)作业手机同步练习。2024年【建筑电工(建筑特…

中国互联网的早期形态

1 大约是从 1991 年开始&#xff0c;国内开始了第一个 BBS 站——北京长城站&#xff0c;经过长时间发展&#xff0c;直到 1995 年&#xff0c;随着计算机及其外设的大幅降价&#xff0c;BBS 才逐渐被部分人们所认识。少数玩 BBS 站的“极客”站长&#xff0c; 基于个人关系&am…

定时关机应用V2.1

# 在ShutDown_2.0的基础上&#xff0c;作了如下改进&#xff1a; # 1) 修正了默认模式无法选择其他时间的bug&#xff0c;还增加了2.5小时和3小时两个选项&#xff1b; # 2&#xff09;自定义模式将计时单位从“秒”改为“分钟”&#xff0c;倒计时显示也优化为“小时:分钟:秒”…

C++初阶类与对象(二):详解构造函数和析构函数

上次为类与对象开了一个头&#xff1a;C初阶类与对象&#xff08;一&#xff09;&#xff1a;学习类与对象、访问限定符、封装、this指针 今天就来更进一步 文章目录 1.类的6个默认成员函数2.构造函数2.1引入和概念2.2构造函数特性2.2.1特性1~42.2.2注意2.2.3特性5~72.2.4注意 …

CVE2020-1938漏洞复现

这个漏洞是tomcat的 然后我们先了解漏洞产生的原理 首先我们先来看tmocat纠结是干什么的 tomcat是个中间件 最主要的两个结构、 servlet的定义和部分源码&#xff0c; 漏洞就是从这来的 tomcat处理http请求 源码分析 tomcat 8.5.46 哎 这教学视频讲半天看不懂 不看原…

java打包及上传到私服务

一、准备Maven私服Nexus 添加saas.maven 仓库地址&#xff1a;http://192.168.31.109:8081/repository/saas.maven 二、新建SpringBoot项目com.saas.pdf 添加类&#xff1a;PdfUtil.java package com.saas.pdf;public class PdfUtil {public static void Save(String fileP…

爬虫笔记(一):实战登录古诗文网站

需求&#xff1a;登录古诗文网站&#xff0c;账号&#xff0b;密码&#xff0b;图形验证码 第一&#xff1a;自己注册一个账号&#xff0b;密码哈 第二&#xff1a;图形验证码&#xff0c;需要一个打码平台&#xff08;充钱&#xff0c;超能力power&#xff01;&#xff09;或…

Java医院信息管理系统

技术框架&#xff1a; springboot shiro layui jquery thymeleaf nginx 有需要的可以联系我。 运行环境&#xff1a; jdk8 mysql IntelliJ IDEA maven项目功能&#xff1a; 本项目是用springbootlayuishiro写的医院管理系统&#xff0c;系统的业务比较复杂&#x…

[python]裁剪文件夹中所有pdf文档并按名称保存到指定的文件夹

最近在写论文的实验部分&#xff0c;由于latex需要pdf格式的文档&#xff0c;审稿专家需要对pdf图片进行裁剪放大&#xff0c;以保证图片质量。 原图&#xff1a; 裁剪后的图像&#xff1a; 代码粘贴如下。将input_folder和output_folder替换即可。(x1, y1)&#xff0c; (x2…

linux java 8安装

tar -zxf jdk-8u***.tar.gz -C /usr/loacl/ vim /etc/profile i 输入 export JAVA_HOME/usr/local/安装文件名 export PATH${JAVA_HOME}/bin:$PATH ESC :wq 保存退出 source /etc/profile 验证 java -version

【GAMES101】Lecture 08 着色频率

目录 着色频率 Flat shading&#xff08;平面着色&#xff09; Gouraud shading&#xff08;顶点着色&#xff09; Phong shading&#xff08;像素着色&#xff09; 如何计算法线 着色频率 大家可以看到下面这三个球是看起来不一样的是吧&#xff0c;但是其实这三个球用的…

前端面试题汇总大全(含答案)-- 持续更新

​一、HTML 篇 1. 简述一下你对 HTML 语义化的理解&#xff1f; 用正确的标签做正确的事情。 html 语义化让页面的内容结构化&#xff0c;结构更清晰&#xff0c;便于对浏览器、搜索引擎解析&#xff1b;即使在没有样式 CSS 情况下也以一种文档格式显示&#xff0c;并且是容易…

【算法】使用优先级队列(堆)解决算法题(TopK等)(C++)

文章目录 1. 前言2. 算法题1046.最后一块石头的重量703.数据流中的第K大元素 2.5 如何选择大根堆 与 小根堆&#xff1f; 为什么选择大根堆&#xff08;小根堆&#xff09;&#xff1f;692.前K个高频单词295.数据流的中位数 1. 前言 我们知道&#xff1a;优先级队列是一种常用…

前端react入门day03-react获取dom与组件通信

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 受控表单绑定 React中获取DOM 组件通信 父传子 父传子-基础实现 父传子-props说明 父传子 - 特殊的…

初创公司都应该知道的20个GPT提示词和免费的GPT工具

在不断发展的初创企业环境中&#xff0c;利用 ChatGPT 等尖端工具可以改变游戏规则。以其敏捷性和创新性而闻名的初创企业总是在寻找提高效率、创造力和竞争力的方法。ChatGPT 凭借其先进的功能&#xff0c;成为这一追求中的宝贵资源。 在这篇博文中&#xff0c;我们深入研究了…

力扣第236题——二叉树的最近公共祖先 (C语言题解)

题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以…

【轮式平衡机器人】——软硬件配置/准备

本系列以轮式平衡移动机器人为例&#xff0c;将使用基于模型设计&#xff08;MBD&#xff09;方法进行介绍&#xff0c;涉及基础硬件、软件、控制算法等多方面内容&#xff0c;结合MATLAB/Simulink的强大仿真能力和代码生成能力辅助设计&#xff01;在此过程中可以系统了解开发…

Elastic Stack(1):Elastic Stack简介

1 简介 ELK是一个免费开源的日志分析架构技术栈总称&#xff0c;官网https://www.elastic.co/cn。包含三大基础组件&#xff0c;分别是Elasticsearch、Logstash、Kibana。但实际上ELK不仅仅适用于日志分析&#xff0c;它还可以支持其它任何数据搜索、分析和收集的场景&#xf…

将 SQL Server 2022 数据库备份到 MinIO

Microsoft 在将 S3 连接器和 Polybase 添加到 SQL Server 2022 时取得了重大飞跃。因此&#xff0c;企业可以利用他们保存到对象存储中的大量数据&#xff0c;并使用它来丰富 SQL Server 表。他们还可以利用对象存储来备份 SQL Server&#xff0c;这是开放性和云原生灵活性的又…