java算法day2

  • 螺旋矩阵
  • 搜索插入位置
  • 查找元素第一个位置和最后一个位置

螺旋矩阵

请添加图片描述
请添加图片描述

解法:模拟,核心在于你怎么转,还有就是处理边界,边界如何收缩,什么时候停止旋转。最内圈的时候怎么处理。

通过上图的模拟来解决这个问题:
1.每条边都采取这种左闭又开来进行统一的处理。
2.分别设置四个边界,left = 0,right = matrix[0].length-1, top = 0,bottom = matrix.length-1。
3.每轮:从左上角开始转一圈,这个转圈就相当于遍历然后把结果加入进结果集。这里建议自己创建一个变量用于遍历,不要用前面预定义的量。每条边处理完就边界++。
4.什么时候停:从图中,最内部那里的处理显然就是已经停止转了。这里显然就不是循环的逻辑了,所以到内部这里就该停止。
5.这里就分两种情况,上面图里面画出来了。
第一种:属于长比宽高,这样转最终导致最后需要处理一行,此时上边界和下边界相等,而左边界和右边界不等。
第二种:属于宽比长高,这样转最终导致最后需要处理一列,此时左边界和右边界相等,而上边界和下边界不等。

所以就可以总结出啥时候停止转动,就是当上两种有其中一种情况出现时,就可以停止转了。
while(top<bottom && left<right) 。

这两种情况搞个if else 做判断处理这两种情况就行了。

class Solution {public List<Integer> spiralOrder(int[][] matrix) {int top = 0;int bottom = matrix.length-1;int left = 0;int right = matrix[0].length-1;List<Integer> list = new ArrayList<>();while(top<bottom && left<right){for(int i = left;i<right;i++)list.add(matrix[top][i]);for(int i = top;i<bottom;i++)list.add(matrix[i][right]);for(int i = right;i>left;i--)list.add(matrix[bottom][i]);for(int i = bottom;i>top;i--)list.add(matrix[i][left]);++left;--right;++top;--bottom;}if(bottom == top){for(int i = left;i<=right;i++){list.add(matrix[top][i]);}}else if(left == right){for(int i = top;i<=bottom;i++){list.add(matrix[i][top]);}}return list;}
}

搜索插入位置

注意这个题有一个很大的前提:自增不重复。
由于是有序自增不重复,涉及搜索,最快的肯定就是二分查找。所以直接写二分。
写法1:二分,左闭右闭写法。
这种处理,即left = 0。right = nums.length-1。每次处理,两侧都是封闭的区间。
所以while的条件是left<=right。可以取等,因为两侧闭区间,当相遇的时候是有意义的。
从模拟的结果来说
这里还有一个剪枝的优化。nums[mid] == target这个位置可以停,因为当相等的时候,插前面后面都一样。
否则最终插入位置都会在left停止的位置。(自己模拟一下)。

如果左闭右闭,你不进行+1或者-1操作,会发生死循环。看下面这个图的这个例子就懂了

请添加图片描述

快速记忆:二分,左闭右闭,mid剪枝早停,最终left。

请添加图片描述

class Solution {public int searchInsert(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;  //技巧剪枝判断早停}else if(nums[mid]>target){right = mid - 1; //这是封闭区间的处理,就是由于那个格子有意义,所以才进行-1.下面的left的处理是同理。}else{left = mid +1 ;}}return left;  //自己模拟,最后就是在left停下}
}

查找元素第一个位置和最后一个位置

解法仍然是二分

**这个题仍然是递增,但是和上一题的区别就在于这个题有重复数字。上一题是没有的。**这个题如果还用上面那个题的思维,那么会出现一个情况,虽然插入后得到的数组看上去没问题,但实际上这个插入位置不一定是题目想要的第一个位置和最后一个位置。看下面这个图。
请添加图片描述
用上一个题的思路二分下来就会有这样的问题,这个指向的位置,不一定是边界。

怎么办:思路:
这里我肯定是想继续往左边找,想办法找到左边界。我们只需改在

target <= nums[mid] 时,让 right = mid - 1即可,这样我们就可以继续在 mid 的左区间继续找 5 。

怎么理解这个操作:
本来是target<nums[mid]。这里变<=。当target<nums[mid]时,就是要往左区间去找目标。而这里取一个等,就是说明这里是有可能有target = nums[mid]的可能性。但是这个mid不一定是最左,所以此时改变右区间的时候,右边界往左边再移动一格(往左边继续搜)。

这里可能有一个问题,万一这个就是左边界怎么办?
继续往后推导,最后left会停在结果的位置。所以不用担心。
直接上推导图。请添加图片描述
请添加图片描述

找上边界就是反过来。逻辑同理,想办法往右边搜,那就是target>=nums[mid],即左边有可能会摸到,但是我还是要往右边挪动一格,那就left = mid + 1.最后right会停在最终的最后一个元素。

现在就直接写两个函数调用就完事了。

class Solution {public int[] searchRange(int[] nums, int target) {int left = leftIndex(nums,target);int right = rightIndex(nums,target);// if(nums[left] != target || nums[right] != target){//     return new int[]{-1,-1};// } if(left > right ){return new int[]{-1,-1};}return new int[]{left,right};}public static int leftIndex(int[] nums,int target){int left = 0;int right = nums.length - 1;while(left<=right){int mid = left + (right - left)/2;if(target<=nums[mid]){right = mid -1;}else{left = mid + 1;}}return left;}public static int rightIndex(int[] nums,int target){int left = 0;int right = nums.length - 1;while(left<=right){int mid = left + (right-left)/2;if (target>=nums[mid]){left = mid + 1;}else{right = mid -1;}}return right;}
}

要注意的细节:
1.关于target<=nums[mid]和target>=nums[mid],为什么找左边界要用前者,右边界要用后者。这里用反了就做不出来?
前者:可以发现找左边界的原理是不断的压缩左边维护的区间,所以target<=nums[mid]就可以使得维护的重复右边界往左边收缩。
后者:右边界的原理就是不断的压缩右边维护的区间,所以target<=nums[mid]就可以使得维护的重复左边界往左边收缩。

2.特判

// if(nums[left] != target || nums[right] != target){//     return new int[]{-1,-1};// } 

这里千万不能这么写。必须这样写:

if(left > right ){return new int[]{-1,-1};}

这个例子用于判断当target不在数组中。
先说结果:
当leftIndex执行结束后,left变量指向的是第一个大于target元素的位置,或者是数组长度(如果target大于所有元素)。
当rightIndex指向结束后,right指向的是最后一个小于target的元素的位置,或者是-1(如果target小于所有元素)

看模拟就懂了
nums = [5, 7, 7, 8, 8, 10],目标值 target = 6。
执行 leftIndex:
初始:left = 0, right = 5
第一次循环:mid = 2 (nums[2] = 7), 7 > 6 -> right = 1
第二次循环:mid = 0 (nums[0] = 5), 5 < 6 -> left = 1
第三次循环:mid = 1 (nums[1] = 7), 7 > 6 -> right = 0
循环结束:left = 1
可以看出最后left停留在第一个大于target元素的位置。

执行 rightIndex:
初始:left = 0, right = 5
第一次循环:mid = 2 (nums[2] = 7), 7 > 6 -> right = 1
第二次循环:mid = 0 (nums[0] = 5), 5 < 6 -> left = 1
第三次循环:mid = 1 (nums[1] = 7), 7 > 6 -> right = 0
循环结束:right = 0
可以看出最后left停留在第一个小于target元素的位置。

综上,在这个例子中,最后那肯定left>right了。

3.有可能会想到这个例子nums = []。
这个也包含在里面处理了,这样一开始就left>right了。最终left = 0,right = -1.所以也满足left>right.

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

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

相关文章

SpringBoot-自定义注解AOP实现及拦截器示例

SpringBoot-自定义注解AOP实现及拦截器示例 一、四大元注解 当你在编写自定义注解时&#xff0c;Target、Retention、Documented 和 Inherited 是四个你可能会用到的元注解&#xff0c;它们可以帮助你更好地定义和使用注解。 1、Target Target 注解用于指定注解可以应用的程…

【科研入门】评价指标AUC原理及实践

评价指标AUC原理及实践 目录 评价指标AUC原理及实践一、二分类评估指标1.1 混淆矩阵1.2 准确率 Accuracy定义公式局限性 1.3 精确率 Precision 和 召回率 Recall定义公式 1.4 阈值定义阈值的调整 1.5 ROC与AUC引入定义公式理解AUC算法 一、二分类评估指标 1.1 混淆矩阵 对于二…

【muzzik 分享】关于 MKFramework 的设计想法

MKFramework是我个人维护持续了几年的项目&#xff08;虽然公开只有一年左右&#xff09;&#xff0c;最开始由于自己从事QP类游戏开发&#xff0c;我很喜欢MVVM&#xff0c;于是想把他做成 MVVM 框架&#xff0c;在论坛第一个 MVVM 框架出来的时候&#xff0c;我的框架已经快完…

电机控制专题(二)——Sensorless之扩展反电动势EEMF

文章目录 电机控制专题(二)——Sensorless之扩展反电动势EEMF前言理论推导仿真验证总结参考文献 电机控制专题(二)——Sensorless之扩展反电动势EEMF 前言 总结下电机控制中的扩展反电动势模型。 纯小白&#xff0c;如有不当&#xff0c;轻喷&#xff0c;还请指出。 在得出E…

synchronized锁升级原理

锁升级过程 jdk1.6之后的优化 synchronized锁有四种状态&#xff0c;无锁&#xff0c;偏向锁&#xff0c;轻量级锁&#xff0c;重量级锁&#xff0c;这几个状态会随着竞争状态逐渐升级&#xff0c;锁可以升级但不能降级&#xff0c;但是偏向锁状态可以被重置为无锁状态。 1、偏…

深入挖掘C语言 ---- 文件操作

目录 1. 文件的打开和关闭1.1 流和标准流1.1.1流1.1.2标准流 1.2 文件指针1.3 文件的打开和关闭 2. 顺序读写3. 随机读写3.1 fseek3.2 ftell3.3 rewind 4. 读取结束判定 正文开始 1. 文件的打开和关闭 1.1 流和标准流 1.1.1流 我们程序的数据需要输出到各种外部设备, 也需要…

CentOS7升级openssl

文章目录 一 系统环境二 操作步骤三 版本检查 一 系统环境 公司服务器等保要求&#xff0c;修复openssl的高危漏洞。 本机使用centos7.9系统&#xff0c;openssl版本是1.0.2k&#xff0c;计划升级到1.1.1q 在执行下列操作前&#xff0c;务必要打快照做好备份&#xff0c;以防升…

浮点数随机生成器

浅做了一个数值模拟器&#xff0c;支持自定义多路数据模拟。数据源支持浮点型、整形等多种类型&#xff0c;通讯支持网口和串口&#xff0c;支持指定协议。简略效果大概如下&#xff0c;后续可能会考虑开源~ [code] 浮点数生成器 #include <iostream> #include <ra…

Scala 04 —— 函数式编程底层逻辑

函数式编程 底层逻辑 该文章来自2023/1/14的清华大学交叉信息学院助理教授——袁洋演讲。 文章目录 函数式编程 底层逻辑函数式编程假如...副作用是必须的&#xff1f;函数的定义函数是数据的函数&#xff0c;不是数字的函数如何把业务逻辑做成纯函数式&#xff1f;函数式编程…

【python】直接在python3下安装 jupyter notebook,以及处理安装报错,启动不了问题

目录 问题&#xff1a; 1 先做准备&#xff0c;查看环境 1.1 先看python3 和pip &#xff0c;以及查看是否有 juypter 1.2 开始安装 1.3 安装完成后得到警告和报错 2 处理安装的报错问题 2.1 网上有说是因为 pip 自身需要更新&#xff0c;更新之 2.1.1 更新pip 2.1.…

Redis搭建主从

Redis搭建主从: 1:拉取Redis镜像 docker pull redis2:创建主从对应的目录结构 3:对redis6379.log,redis6380.log,redis6381.log进行授权 chmod 777 redis6379.log chmod 777 redis6380.log chmod 777 redis6381.log4:修改主(master)的配置文件 5:创建主(master) redis_6379 …

docker部署java项目,如何docker-compose内的jdk版本与本地版本保持一致

目录结构 /var └── data├── docker-compose.yml └── docker├── Dockerfile└── jdk-8u401-linux-x64.tar.gzdockerfile文件 FROM ubuntu:latest# 拷贝本地服务器上的 JDK 安装包到 Docker 镜像中 COPY jdk-8u401-linux-x64.tar.gz /jdk-8u401-linux-x64.tar.g…

基于弹簧鞘复合纱和迁移学习算法的可穿戴人体重构和智能试衣系统

研究背景 在信息时代和元宇宙的背景下&#xff0c;虚拟服装设计对满足服装行业的个性化需求至关重要。与传统方法不同&#xff0c;虚拟试衣节省时间、方便客户&#xff0c;并提供多样化的款式。准确得测量人体围度并重构出人体的模型是虚拟试衣的关键。为了实现动态人体重构&a…

【面试经典 150 | 二叉树层序遍历】二叉树的右视图

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;层序遍历方法二&#xff1a;深度优先搜索 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于…

【Linux】进程和计划任务

目录 一、进程介绍 1.1 进程与线程的定义 1.1.1 进程(Process)** 1.1.2 线程(Thread)** 1.1.3 进程与线程的区别 1.2 进程的特征 1.3 进程状态 1.3.1 进程的基本状态 1.3.2 进程更多的状态 1.4 进程的优先级 1.5 进程间通信 1.6 进程的分类* 二、进程管理 2.1 查看…

SpringBoot项目创建及简单使用

目录 一.SpringBoot项目 1.1SpringBoot的介绍 1.2SpringBoot优点 二.SpringBoot项目的创建 三.注意点 一.SpringBoot项目 1.1SpringBoot的介绍 Spring是为了简化Java程序而开发的&#xff0c;那么SpringBoot则是为了简化Spring程序的。 Spring 框架&#xff1a; Spring…

【UKE!】2024.4.19

2024.4.19 【你知道的都是真相。只可惜那些并不是真相的全部。】 Friday 三月十一 谷雨 <BGM “谷雨–音阙诗听”> AC :Answer Coarse,粗劣的答案 ​ CE :Compile Easily,轻松通过 ​ PC :Perfect Compile 完美的编译 ​ WA :Wonderful Answer,好答案 ​ RE :Run Exce…

【InternLM 实战营第二期作业04】XTuner微调LLM:1.8B、多模态、Agent

基础作业 训练自己的小助手认知 1.环境安装 安装XTuner 源码 # 如果你是在 InternStudio 平台&#xff0c;则从本地 clone 一个已有 pytorch 的环境&#xff1a; # pytorch 2.0.1 py3.10_cuda11.7_cudnn8.5.0_0studio-conda xtuner0.1.17 # 如果你是在其他平台&#x…

SpringSecurity源码分析3--UserDetail部分

前言&#xff1a;本章提及的类都是与用户名、密码相关的类 UserDetailsService.class 用于加载用户信息 DaoAuthenticationProvider.class 将数据库的信息拿出来进行认证 AbstractUserDetailsAuthenticationProvider.class DaoAuthenticationProvider的父类&#xff0c;通过模…

【FreeRTOS】RTOS任务的同步与互斥:(二)信号量

【FreeRTOS】RTOS任务的同步与互斥&#xff1a;&#xff08;二&#xff09;信号量 信号量概念二值信号量二值信号量概念二值信号量相关API函数二值信号量的案例设计cubeMX配置软件程序设计 计数型信号量计数型信号量概念计数型信号量相关API函数二值信号量的案例设计cubeMX配置…