[Java 算法] 二分查找

练习一 : 二分查找

704. 二分查找 - 力扣(LeetCode)

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

算法原理 :

  1. 数组必须有序
  2. 每次取中间位置 , 和目标位置比较
  3. 比目标小->去右边找
  4. 比目标大->去左边找
  5. 直到找到或找不到

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

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

class Solution { public int[] searchRange(int[] nums, int target) { int len = nums.length; int left = 0,right = len-1,mid = 0; int[] ret = {-1,-1}; if(len == 0||nums[len-1]<target||nums[0]>target){//把数组为空必免指针越界的优先级排到最高 return ret; } //找左端点 int retleft = 0; while(left<right){ mid = left+(right-left)/2; //找左端点时,如果存在则最后mid会落在left处,经过处理会让两个指针重合,退出循环,返回结果 if(nums[mid]<target){ left = mid+1; }else{ right = mid; } } //判断双指针重合处是否是端点 if(nums[left] != target){ return ret; } retleft = left; //找右端点 int retright = 0; left = 0; right = len-1;//记得恢复指针 while(left<right){ mid = left+(right-left+1)/2; //找右端点时,如果存在则最后mid会落在right处,经过处理会让left和right重合,退出循环,返回结果 if(nums[mid]<=target){ left = mid; }else { right = mid-1; } } retright = right; //经过找左端点后如果进入到寻找右端点,则数组中一定包含target,此时不需要进行判断 ret[0] = retleft; ret[1] = retright; return ret; } }

算法原理 :

找左端点 :

  • 当 mid 落在<target 处 , 要让 left 跳出非法区域(left = mid+1)
  • 当 mid 落在>=target 处 , 要让 right 移到 mid 处(right = mid),因为不能保证 mid-1 和 mid 处是否是左端点
  • 当退出本次循环时 , 还需要判断一下双指针重合位置是否是 target

找右端点 :

  • 和找左端点同理;当 mid 落在<=target 处 , 要让 left 移到 mid 处(left = mid),因为不能保证 mid+1 和 mid 处是右端点
  • 当 mid 落在>target 处 , 要让 right 跳出非法区域(right = mid-1)
  • 能进入此次循环,意味着数组中一定包含 target , 所以不需要判断双指针位置的合法性(即使数组中只有一个 target)

注意 :

  1. 循环条件 : left<right

因为当只有当两指针重合时(right == left) , 才能退出循环 , 判断合法性 ; 如果写成 left<=right , 则最后一步 right == left ==mid 时会一直死循环

  1. mid 处理过程(防止溢出和死循环)

找左端点 → 用「左中位数」:mid = left + (right - left)/2

找右端点 → 用「右中位数」:mid = left + (right - left + 1)/2

左中数 : 处理后 mid 会更靠近 left , 直到 等于 left ; 目的是让 right 主动向左收敛 , 最终重合

右中数 : 处理后 mid 会更靠近 right , 直到 等于 righr ; 目的是让 left 主动向右收敛 , 最终重合

核心模板 :

练习三 : 搜索插入位置

35. 搜索插入位置 - 力扣(LeetCode)

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

练习四 : x 的平方根

69. x 的平方根 - 力扣(LeetCode)

class Solution {     public int searchInsert(int[] nums, int target) {         int left = 0, right = nums.length - 1;         while (left <= right) {             int mid = left + (right - left) / 2;             if (nums[mid] == target) {                 return mid; // 找到目标,返回下标             } else if (nums[mid] < target) {                 left = mid + 1; // 目标在右侧             } else {                 right = mid - 1; // 目标在左侧             }         }         // 循环结束没找到,left 就是插入位置         return left;     } }

Read more

C++ STL set 系列完全指南:从底层原理、核心接口到实战场景

C++ STL set 系列完全指南:从底层原理、核心接口到实战场景

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. 容器分类:序列式容器与关联式容器的本质区别 * 二. set 系列核心原理:红黑树赋能的高效特性 * 三. set 核心接口实战:基于实操代码详解 * 3.1 初始化与插入:去重 + 自动排序 * 3.2 查找与删除:精准操作单个元素 * 3.3 区间操作:lower_bound 与 upper_bound * 四. multiset:支持重复 key 的关联式容器 * 五. set 系列的实战价值:解决实际开发问题

By Ne0inhk
【Java 开发日记】我们来说一说 JVM 的内存模型

【Java 开发日记】我们来说一说 JVM 的内存模型

目录 前言 JVM 内存结构(运行时数据区) 1. 程序计数器 2. Java 虚拟机栈 3. Java 堆 4. 方法区 5. 运行时常量池 直接内存 总结与对比 前言 JVM 内存结构(JVM Memory Structure) 和 Java 内存模型(Java Memory Model, JMM) 是两个不同的概念,但经常被混淆。 1. JVM 内存结构:指的是 JVM 在运行时,其内部的数据存储区域是如何划分的(如堆、栈、方法区等)。这是我们接下来要讲解的重点。 2. Java 内存模型:是一个概念和规范,它定义了多线程环境下,

By Ne0inhk
如何解决IDEA/Datagrip无法连接数据库的问题:解决方法为添加参数-Djava.net.preferIPv4Stack=true

如何解决IDEA/Datagrip无法连接数据库的问题:解决方法为添加参数-Djava.net.preferIPv4Stack=true

如何解决IDEA/Datagrip无法连接数据库的问题:解决方法为添加参数-Djava.net.preferIPv4Stack=true 引言 在开发过程中,我们常常使用集成开发环境(IDE)如 IntelliJ IDEA 或 JetBrains DataGrip 来与数据库进行交互。然而,有时可能会遇到无法连接数据库的情况,尤其是当使用新版的 IDEA 或 DataGrip 时。这种问题通常是由于网络配置或者 IDE 与数据库之间的兼容性问题引起的。 一种常见的解决办法是添加 JVM 参数 -Djava.net.preferIPv4Stack=true,以优先使用 IPv4 协议栈。这种方式能够有效解决因 IPv6 配置问题导致的数据库连接失败问题。本文将详细介绍如何通过修改 IDEA 或 DataGrip 的启动参数来解决这个问题。 文章目录 * 如何解决IDEA/Datagrip无法连接数据库的问题:解决方法为添加参数-Djava.net.

By Ne0inhk
Java 大视界 -- Java+Flink CDC 构建实时数据同步系统:从 MySQL 到 Hive 全增量同步(443)

Java 大视界 -- Java+Flink CDC 构建实时数据同步系统:从 MySQL 到 Hive 全增量同步(443)

Java 大视界 -- Java+Flink CDC 构建实时数据同步系统:从 MySQL 到 Hive 全增量同步(443) * 引言: * 正文: * 一、 核心认知:Flink CDC 与全增量同步逻辑 * 1.1 Flink CDC 核心原理 * 1.1.1 与传统数据同步方案的对比(实战选型参考) * 1.2 全增量同步核心逻辑(MySQL→Hive) * 1.2.1 关键技术点(实战必关注,每个点都踩过坑) * 二、 环境准备:生产级环境配置(可直接复用) * 2.1 核心依赖配置(pom.xml)

By Ne0inhk