代码随想录算法训练营第59天| 503.下一个更大元素II 42. 接雨水

java代码编写

503.下一个更大元素II

给定一个循环数组 numsnums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素

数字 x下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1

示例 1:

输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

示例 2:

输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]

提示:

  • 1 <= nums.length <= 104
  • -109 <= nums[i] <= 109

教程:https://programmercarl.com/0503.%E4%B8%8B%E4%B8%80%E4%B8%AA%E6%9B%B4%E5%A4%A7%E5%85%83%E7%B4%A0II.html

方法一:暴力解法

思路:和739. 每日温度的暴力解法差不多,区别是这里要循环找下一个比当前大的。

区别就是默认填充-1,第二个循环要进行循环遍历。

内循环j的范围调整为i+n,下标通过对n取余遍历到前面的索引。

力扣上可以通过,执行90ms,内存44.76MB。

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n ) O(n) O(n)
class Solution {public int[] nextGreaterElements(int[] nums) {int n = nums.length;int[] res = new int[n];Arrays.fill(res, -1); // 填充res数组为-1for (int i = 0; i < n; i++) {for (int j = i + 1; j < i + n; j++) {int index = j % n; // 通过取余实现循环数组if (nums[index] > nums[i]) {res[i] = nums[index];break;}}}return res;}
}

方法二:单调栈

思路:和方法一有相似之处,都是使用取余的方式来控制循环找比当前大的下标。

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)
import java.util.Arrays;
import java.util.Stack;class Solution {public int[] nextGreaterElements(int[] nums) {//边界判断if(nums == null || nums.length <= 1) {return new int[]{-1};}int n = nums.length;int[] result = new int[n];//存放结果Arrays.fill(result,-1);//默认全部初始化为-1int a=0;Stack<Integer> st= new Stack<>();//栈中存放的是nums中的元素下标for(int i = 0; i < 2*n; i++) {while(!st.empty() && nums[i % n] > nums[st.peek()]) {a = st.peek();System.out.println(a);result[st.peek()] = nums[i % n];//更新resultst.pop();//弹出栈顶}st.push(i % n);}return result;}public static void main(String[] args) {Solution solution = new Solution();int[] result = solution.nextGreaterElements(new int[]{1,2,1});for (int num : result) {System.out.print(num + " ");}}
}

这里利用栈的特性,拿nums = [1,2,1]为例子说,

i=0时,首先将下标0放入栈;

i=1时,栈非空,num[1]>nums[栈顶元素]也就是nums[1]>nums[0],是的2>1,所以result[0]=nums[1]=2,将栈顶元素0出栈,此时栈为空,将1再入栈;

i=2时,栈非空,num[2]>nums[栈顶元素]也就是nums[2]>nums[1],是的1>2,假的,所以将2入栈,此时栈中元素为1,2;

i=3时,栈非空,num[3%3]>nums[栈顶元素]也就是nums[0]>nums[2],是的1>1,假的,所以将0入栈,此时栈中元素为1,2,0;

i=4时,栈非空,num[4%3]>nums[栈顶元素]也就是nums[1]>nums[0],是的2>1,真的,所以result[栈顶元素]=result[0]=nums[1]=2,将栈顶元素0出栈;num[4%3]>nums[栈顶元素]也就是nums[1]>nums[2],是的2>1,真的, 所以result[栈顶元素]=result[2]=nums[1]=2,将栈顶元素2出栈;num[4%3]>nums[栈顶元素]也就是nums[1]>nums[1],退出while循环,将1入栈,此时栈中元素为1,1;

i=5时,栈非空,num[5%3]>nums[栈顶元素]也就是nums[2]>nums[1],是的1>2,假的,所以将2入栈,此时栈中元素为1,1,2;

i<6退出循环,结束,此时result=[2,-1,2].

看看栈的特性,又有点忘了

import java.util.Stack;public class StackExample {public static void main(String[] args) {// 创建一个整数类型的栈Stack<Integer> stack = new Stack<>();// 将元素压入栈顶stack.push(10);stack.push(20);stack.push(30);// 查看栈顶元素System.out.println("栈顶元素:" + stack.peek()); // 输出:30// 弹出栈顶元素int poppedElement = stack.pop();System.out.println("弹出的栈顶元素:" + poppedElement); // 输出:30// 查看栈顶元素(此时栈顶元素为20)System.out.println("栈顶元素:" + stack.peek()); // 输出:20// 判断栈是否为空System.out.println("栈是否为空:" + stack.isEmpty()); // 输出:false// 获取栈的大小System.out.println("栈的大小:" + stack.size()); // 输出:2// 遍历栈元素System.out.print("栈中的元素:");while (!stack.isEmpty()) {System.out.print(stack.pop() + " ");}// 输出:20 10// 栈现在为空System.out.println("\n栈是否为空:" + stack.isEmpty()); // 输出:true}
}

42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

img

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

教程:https://programmercarl.com/0042.%E6%8E%A5%E9%9B%A8%E6%B0%B4.html

方法一:暴力解法

思路:两个循环,关键我想不出正常的解题思路。这个在力扣上超时。

42.接雨水1

首先,如果按照列来计算的话,宽度一定是1了,我们再把每一列的雨水的高度求出来就可以了。

可以看出每一列雨水的高度,取决于,该列 左侧最高的柱子右侧最高的柱子最矮的那个柱子的高度。

来举一个理解,例如求列4的雨水高度,如图:

42.接雨水3

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)
class Solution {public int trap(int[] height) {int sum = 0;for (int i = 0; i < height.length; i++) {// 第一个柱子和最后一个柱子不接雨水if (i==0 || i== height.length - 1) continue;int rHeight = height[i]; // 记录右边柱子的最高高度int lHeight = height[i]; // 记录左边柱子的最高高度for (int r = i+1; r < height.length; r++) {if (height[r] > rHeight) rHeight = height[r];}for (int l = i-1; l >= 0; l--) {if(height[l] > lHeight) lHeight = height[l];}int h = Math.min(lHeight, rHeight) - height[i];if (h > 0) sum += h;}return sum;}public static void main(String[] args) {Solution solution = new Solution();int sum = solution.trap(new int[]{4,2,0,3,2,5});System.out.println(sum);}
}

方法二:双指针法

思路:就是暴力解法的升级版。在暴力解法的基础上,直接将每个i的左侧最高的柱子和右侧最高的柱子存入数组,减少遍历次数,用的时候直接拿。

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)
class Solution {public int trap(int[] height) {int length = height.length;if (length <= 2) return 0;int[] maxLeft = new int[length];int[] maxRight = new int[length];// 记录每个柱子左边柱子最大高度maxLeft[0] = height[0];for (int i = 1; i< length; i++) maxLeft[i] = Math.max(height[i], maxLeft[i-1]);// 记录每个柱子右边柱子最大高度maxRight[length - 1] = height[length - 1];for(int i = length - 2; i >= 0; i--) maxRight[i] = Math.max(height[i], maxRight[i+1]);// 求和int sum = 0;for (int i = 0; i < length; i++) {int count = Math.min(maxLeft[i], maxRight[i]) - height[i];if (count > 0) sum += count;}return sum;}
}

方法三:单调栈

思路:给我我是想不起来用单调栈的。

单调栈就是保持栈内元素有序。和栈与队列:单调队列 (opens new window)一样,需要我们自己维持顺序,没有现成的容器可以用。

1.单调栈是按照行方向来计算雨水,如图:

42.接雨水2

2.使用单调栈内元素的顺序

从大到小还是从小到大呢?

从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。

因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。

3.遇到相同高度的柱子怎么办。

遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。

例如 5 5 1 3 这种情况。如果添加第二个5的时候就应该将第一个5的下标弹出,把第二个5添加到栈中。

因为我们要求宽度的时候 如果遇到相同高度的柱子,需要使用最右边的柱子来计算宽度

4.栈里要保存什么数值

使用单调栈,也是通过 长 * 宽 来计算雨水面积的。

长就是通过柱子的高度来计算,宽是通过柱子之间的下标来计算,

那么栈里有没有必要存一个pair<int, int>类型的元素,保存柱子的高度和下标呢。

其实不用,栈里就存放下标就行,想要知道对应的高度,通过height[stack.top()] 就知道弹出的下标对应的高度了。

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)
class Solution {public int trap(int[] height){int size = height.length;if (size <= 2) return 0;// in the stack, we push the index of array// using height[] to access the real heightStack<Integer> stack = new Stack<Integer>();stack.push(0);int sum = 0;for (int index = 1; index < size; index++){int stackTop = stack.peek();if (height[index] < height[stackTop]){stack.push(index);}else if (height[index] == height[stackTop]){// 因为相等的相邻墙,左边一个是不可能存放雨水的,所以pop左边的index, push当前的indexstack.pop();stack.push(index);}else{//pop up all lower valueint heightAtIdx = height[index];while (!stack.isEmpty() && (heightAtIdx > height[stackTop])){int mid = stack.pop();if (!stack.isEmpty()){int left = stack.peek();int h = Math.min(height[left], height[index]) - height[mid];int w = index - left - 1;int hold = h * w;if (hold > 0) sum += hold;stackTop = stack.peek();}}stack.push(index);}}return sum;}
}

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

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

相关文章

怎么为pdf文件添加水印?

怎么为pdf文件添加水印&#xff1f;PDF是一种很好用的文件格式&#xff0c;这种格式能够很有效的保护我们的文件&#xff0c;但有时可能还会被破解&#xff0c;这种时候在PDF上添加水印就是比较好的方法。 综上所述&#xff0c;PDF是保密性很强的文件&#xff0c;但添加水印能够…

数字技术:引领未来的创新驱动力

数字技术&#xff0c;作为当代最具创新性和影响力的技术领域之一&#xff0c;已经在全球范围内引起了广泛的关注和研究。当前&#xff0c;数字技术正以惊人的速度改变着我们的世界&#xff0c;从日常生活到商业领域&#xff0c;无一不受到其影响。数字技术的发展不仅改变了人们…

Nginx快速入门:nginx各类转发、代理配置详解|location、proxy_pass参数详解(五)

0. 引言 咱们上节讲解了nginx的负载均衡配置&#xff0c;但是还有很多其他的转发情况&#xff0c;包括不同路径转发至不同的业务服务&#xff0c;通配符识别路径转发等。 今天一起来学习nginx的转发配置 1. location模块的匹配模式 首先我们要了解nginx进行转发代理的核心在…

【音视频】remb twcc原理

目录 twcc简介 WebRTC REMB 参考文档 twcc简介 TWCC全称是Transport wide Congestion Control&#xff0c;是webrtc的最新的拥塞控制算法。其原理是在接收端保存数据包状态&#xff0c;然后构造RTCP包反馈给发送端&#xff0c;反馈信息包括包到达时间、丢包状态等&#xff…

基于JSP+Servlet+Mysql的调查管理系统

基于JSPServletMysql的调查管理系统 一、系统介绍二、功能展示1.项目内容2.项目骨架3.数据库3.登录4.注册3.首页5.系统管理 四、其它1.其他系统实现五.获取源码 一、系统介绍 项目名称&#xff1a;基于JSPServlet的调查管理系统 项目架构&#xff1a;B/S架构 开发语言&#…

云原生文件存储 CFS 线性扩展到千亿级文件数,百度沧海·存储论文被 EuroSys 2023 录用

恭喜百度沧海云存储和中科大合作的论文《CFS: Scaling Metadata Service for Distributed File System via Pruned Scope of Critical Sections》&#xff08;以下简称论文&#xff09;被 EuroSys 2023 录用。 EuroSys 全称欧洲计算机系统会议&#xff08;The European Confer…

PIC单片机项目(7)——基于PIC16F877A的智能灯光设计

1.功能设计 使用PIC16F877A单片机&#xff0c;检测环境关照&#xff0c;当光照比阈值低的时候&#xff0c;开灯。光照阈值可以通过按键进行设置&#xff0c;同时阈值可以保存在EEPROM中&#xff0c;断电不丢失。使用LCD1602进行显示&#xff0c;第一行显示测到的实时光照强度&a…

移动SEO:如何针对任何设备优化您的网站

您快速进行 Google 搜索并阅读一堆结果。然后&#xff0c;您会发现一些网站具有您正在寻找的答案。 但是你从SERP中选择的第一个&#xff0c;也是最有前途的网站&#xff0c;在你最喜欢的移动设备上无法正常工作。 所以&#xff0c;你关闭它&#xff0c;看看下一个网站是否有…

0x52 背包

0x52 背包 背包是线性DP中一类重要而特殊的模型。 1. 0/1背包 0/1背包问题的模型如下&#xff1a; 给定 N N N个物品&#xff0c;其中第 i i i个物品的体积为 V i V_i Vi​&#xff0c;价值为 W i W_i Wi​。有一个容积为 M M M的背包&#xff0c;要求选择一些物品放入背包&…

乐理基础-节拍器与使用

在 乐理基础-情绪与速度、具体的速度、BPM-CSDN博客 与 乐理基础-抽象的速度-CSDN博客里写了音乐中的速度是怎样去确定的&#xff0c;接下来要写的内容必须要知道怎样去确定音乐的速度才可以。 首先音乐的速度之前用秒来说&#xff0c;是为了方便理解&#xff0c;比如138bpm它…

DC-9靶机

目录 DC-9靶场链接&#xff1a; 首先进行主机发现&#xff1a; sqlmap注入&#xff1a; 文件包含&#xff1a; 端口敲门规则&#xff1a; hydra爆破&#xff1a; root提权&#xff1a; 方法一/etc/passwd&#xff1a; ​编辑 方法二定时任务crontab&#xff1a; DC-9靶…

罗德与施瓦茨FSV40-N手持式频谱分析仪

描述 R&S FSV是速度最快、功能最全面的信号和频谱分析仪&#xff0c;适用于从事RF系统开发、生产、安装和服务的注重性能、注重成本的用户。 频率范围高达3.6 GHz/7 GHz/13.6 GHz/30 GHz 40 MHz分析带宽 0.4 dB级测量不确定度&#xff0c;最高7 GHz 针对GSM/EDGE、WCDMA/…