Java二分算法题目练习

Java二分算法题目练习

二分算法

二分查找

在这里插入图片描述
题目解析:在一个有序数组中找一个target ,找到返回其下标,找不到返回-1
算法原理:1.暴力解法:遍历整个数组进行查找时间复杂度O(N)
2.朴素二分算法:我们可以发现其数组是可以根据一个值将其分为两部分并且可以比较然后舍弃一部分,此时这个数组具有“二段性”,因此可以使用二分算法
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述
classSolution{publicintsearch(int[] nums,int target){//此时就用left和right两个变量在左右两边//使用mid来表示其中间的下标,因为其有序//这样我们每次比较一次其就会干掉一半的数这个效率是很高的int left =0;int right = nums.length -1;while(left <= right){int mid = left +(right - left)/2;//防溢出if(target > nums[mid]){//在[mid+1 , right] left = mid +1;}elseif(target < nums[mid]){//在[left,mid - 1] right = mid -1;}else{return mid;}}return-1;}}
时间复杂度:O(log N )
空间复杂度:O(1)

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

在这里插入图片描述
题目解析:就是给了我们一个target,让我们在一个非递减的数组中找其开始和结束下标,并返回,如果找不到就返回[-1,-1]
解法一:暴力解法 ,时间复杂度O(N)
解法二:朴素二分查找,由于我们不确定找的数是其开始和结束位置,因此有可能全部遍历,因此时间复杂度是O(N)
解法三:左右二分算法
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述
classSolution{publicint[]searchRange(int[] nums,int target){int[] ret =newint[2]; ret[0]= ret[1]=-1;if(nums.length ==0){return ret;}int left =0;int right = nums.length -1;//先左边二分while(left < right){int mid = left +(right - left)/2;if(nums[mid]< target){ left = mid +1;}else{ right = mid;}}//此时left与right相遇就会结束if(nums[left]!= target){return ret;}//反之就找到了左端点 ret[0]= left; left =0;//可以不用重置,因此此时上面left对应就是其开始位置 right = nums.length -1;while(left < right){int mid = left +(right - left +1)/2;if(nums[mid]> target){ right = mid -1;}else{ left = mid;}} ret[1]= right;return ret;}}

x的平方根

在这里插入图片描述
在这里插入图片描述
classSolution{publicintmySqrt(int x){//此时如果x<1,此时只保留整数,就是0if(x <1){return0;}//防止数据超出long left =1;long right = x;while(left < right){long mid = left +(right - left +1)/2;if(mid * mid <= x){ left = mid;}else{ right = mid -1;}}return(int)left;}}

搜索插入位置

在这里插入图片描述
题目解析:在一个无重复元素的升序数组中找出其目标值的位置,但是可能不存在,不存在的话就返回其按顺序插入的位置
二分算法:因为其可以将其数组分为>= target和<target的两部分,并且可以舍弃<target这个部分,因此使用二分算法,并且还是当left 等于 right结束
在这里插入图片描述
classSolution{publicintsearchInsert(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){ left = mid +1;}else{ right = mid;}}//注意此时可能从头到尾都是< targetreturn nums[right]< target ? right +1: right;}}

山脉数组的峰顶索引

在这里插入图片描述
题目解析:在一个一边递增,另一边递减的数组中找出其最大值
因此只需要找出其递增和递减中间的值下标就可以
在这里插入图片描述
class Solution { publicint peakIndexInMountainArray(int[] arr) { //因为其山脉我们呢可以分为两部分//峰值左边是递增的//峰值右边是递减的intleft=0;intright= arr.length -1;while(left<right){ int mid =left+(right-left+1)/2;if(arr[mid -1]< arr[mid]){ left= mid; }else{ right= mid -1; } } returnleft; } } 

寻找峰值

在这里插入图片描述
题目解析:在一个数组中,找其峰值,并且可能有多个,只需返回任意一个就行
二分算法:因为其是必然有峰值的,并且是不存在两个元素相同,因此其会出现两种情况,要么是递增,要么递减,因此按照分类使用二分算法
在这里插入图片描述


在这里插入图片描述
class Solution { publicint findPeakElement(int[] nums) { intleft=0;intright= nums.length -1;while(left<right){ int mid =left+(right-left)/2;if(nums[mid]> nums[mid+1]){ right= mid; }else{ left= mid +1; } } returnleft; } } 

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

在这里插入图片描述
题目解析:原本一个自增的数组,经过旋转,让我们找出其最小的值
算法原理:暴力解法:直接遍历找最小值
二分算法:我们可以以最后一个下标的值为基准值,因此数组可以分为两个部分,一半是>nums[n-1],一半是 <= nums[n - 1],就这样根据二段性就可以使用二分算法\
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述
classSolution{publicintfindMin(int[] nums){int right = nums.length -1;int n = right;int left =0;while(left < right){int mid = left +(right - left)/2;if(nums[mid]> nums[n]){ left = mid +1;}else{ right = mid;}}return nums[left];}}

点名

在这里插入图片描述
题目解析:就是一个递增的数组,并且其下标和其对应的值是对应的,中间缺了一个数导致其不对应了,我们要找到这个数
在这里插入图片描述
//哈希classSolution{publicinttakeAttendance(int[] records){//使用hashSet<Integer> set =newHashSet<>();for(intrecord: records){ set.add(record);}//先全部将其放入hash中,让后一个一个判断其是否在其中就行int len = records.length;for(int i =0; i < len;i++){if(!set.contains(i)){return i;}}//缺少最后一个return len;}}
//直接遍历classSolution{publicinttakeAttendance(int[] records){//直接遍历for(int i =0;i < records.length;i++){if(records[i]!= i){return i;}}return records.length;}}
//求和classSolution{publicinttakeAttendance(int[] records){//使用求和方式也可以int len = records.length;int sum = len *(len +1)/2;for(int i =0;i < len ;i++){ sum -= records[i];}return sum;}}
//位运算classSolution{publicinttakeAttendance(int[] records){//使用位运算符^int ret =0;for(int i =0;i <records.length; i++){ ret ^= records[i]^ i;//此时最后一个下标没有异或}return ret^records.length;}}
//二分算法classSolution{publicinttakeAttendance(int[] records){//此时就可以将其数字分为两个部分//一部分是其值和下标一样//另一部分是不一样int left =0;int right = records.length -1;while(left < right){int mid = left +(right - left)/2;if(records[mid]== mid){ left = mid +1;}else{ right = mid;}}return records[left]== left ? left +1: left;}}

Read more

# Java 零基础完整入门教程(超详细,循序渐进)

# Java 零基础完整入门教程(超详细,循序渐进)

你想要一套完整的Java编程语言入门教程,这份内容从零基础环境搭建到核心语法+实战案例全覆盖,逻辑清晰、知识点完整,学完能掌握Java基础开发能力,适合纯新手入门学习 ✅ 一、Java 简介 & 核心优势(必知) Java 是一门 面向对象、跨平台、编译型+解释型 的高级编程语言,由Sun公司(现Oracle)推出,诞生至今稳居编程语言排行榜前列。 Java 核心三大特性(灵魂) 1. 跨平台(一次编写,到处运行) :Java代码编译后生成字节码文件(.class),不是直接运行在操作系统,而是运行在 JVM(Java虚拟机) 上。不同操作系统(Windows、Mac、Linux)安装对应版本的JVM,就能运行同一个class文件,这是Java最核心的优势。 2. 面向对象(OOP) :Java纯面向对象,万物皆对象,

By Ne0inhk
从Web到AI:Agent Skills安全架构实战——权限控制与数据保护的Java+Vue全栈方案

从Web到AI:Agent Skills安全架构实战——权限控制与数据保护的Java+Vue全栈方案

图片来源网络,侵权联系删。 文章目录 * 1. 当Web安全思维遇见Agent Skills安全 * 2. Web安全架构与Agent Skills安全的基因同源性 * 2.1 安全能力映射表(Web→Skills) * 2.2 Skills安全架构全景图 * 3. Skills安全核心原理(Web架构师视角) * 3.1 三大安全支柱 * 3.2 技能权限控制模型(类比Spring Security) * 3.3 内存级数据保护(类比Web会话安全) * 4. 企业级实战:金融Skills安全防护体系 * 4.1 项目结构(Spring Boot 3 + Vue3) * 4.2 核心安全代码实现 * 5. Web开发者转型Skills安全的痛点解决方案 * 5.1 金融级问题诊断矩阵

By Ne0inhk
Java 中间件:RocketMQ 顺序消息(全局/分区顺序)

Java 中间件:RocketMQ 顺序消息(全局/分区顺序)

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Java中间件这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * Java 中间件:RocketMQ 顺序消息(全局 / 分区顺序) * 什么是顺序消息? * RocketMQ 顺序消息的工作原理 * 全局顺序 vs 分区顺序 * RocketMQ 顺序消息的核心机制 * 全局顺序消息的实现 * 全局顺序的配置要求 * Java 代码示例:全局顺序消息 * 全局顺序的局限性 * 分区顺序消息的实现 * 分区顺序的设计思路 * Java 代码示例:分区顺序消息 * 分区顺序的关键要点 * 顺序消息的消费机制详解 * ConsumeOrderlyStatus 枚举 * 消费失败的处理机制 * 并发消费 vs 顺序消费

By Ne0inhk