目录
- 专栏导读
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 四、解题思路
- 五、Java算法源码
- 六、效果展示
- 1、输入
- 2、输出
- 3、说明
- 七、复杂度分析
- 1、时间复杂度
- 2、空间复杂度
华为OD机试 2023B卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
一贫如洗的樵夫阿里巴巴在去砍柴的路上,无意中发现了抢到集团的藏宝地,藏宝地有编号从0-N的箱子,每个箱子上面有一个数字,箱子排列成一个环,编号最大的箱子的下一个是编号为0的箱子。
请输出每个箱子贴的数字之后的第一个比它大的数,如果不存在则输出-1。
二、输入描述
输入一个数字子串,数字之间使用逗号分隔,例如:1,2,3,1
1 <= 子串中数字个数 <= 10000;
-100000 <= 每个数字值 <= 100000;
三、输出描述
下一个大的数列表,以逗号分隔,例如:2,3,6,-1,6
四、解题思路
我们可以使用单调栈解决本题。单调栈中保存的是下标,从栈底到栈顶的下标在数组 nums 中对应的值是单调不升的。
每次我们移动到数组中的一个新的位置 i,我们就将当前单调栈中所有对应值小于 nums[i] 的下标弹出单调栈,这些值的下一个更大元素即为
nums[i](证明很简单:如果有更靠前的更大元素,那么这些位置将被提前弹出栈)。随后我们将位置 i 入栈。
但是注意到只遍历一次序列是不够的,例如序列 [2,3,1],最后单调栈中将剩余 [3,1],其中元素 [1] 的下一个更大元素还是不知道的。
一个朴素的思想是,我们可以把这个循环数组「拉直」,即复制该序列的前 n−1 个元素拼接在原序列的后面。这样我们就可以将这个新序列当作普通序列,用上文的方法来处理。
而在本题中,我们不需要显性地将该循环数组「拉直」,而只需要在处理时对下标取模即可。
五、Java算法源码
package com.guor.od;
import java.util.*;
public class OdTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] nums = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
int n = nums.length;
int[] ret = new int[n];
Arrays.fill(ret, -1);
Deque<Integer> stack = new LinkedList<Integer>();
for (int i = 0; i < n * 2 - 1; i++) {
while (!stack.isEmpty() && nums[stack.peek()] < nums[i % n]) {
ret[stack.pop()] = nums[i % n];
}
stack.push(i % n);
}
StringBuilder builder = new StringBuilder();
for(int i = 0;i<ret.length;i++){
builder.append(ret[i]).append(",");
}
System.out.println(builder.substring(0,builder.length()-1));
}
}
六、效果展示
1、输入
2,5,2
2、输出
5,-1,5
3、说明
第一个2的下一个最大的数是5,数字5找不到下一个更大的数;
第二个2的下一个最大的数需要循环搜索,结果也是5;
七、复杂度分析
1、时间复杂度
O(n),其中 n 是序列的长度。我们需要遍历该数组中每个元素最多 2 次,每个元素出栈与入栈的总次数也不超过
4 次。
2、空间复杂度
O(n),其中 n 是序列的长度。空间复杂度主要取决于栈的大小,栈的大小至多为 2n−1。
🏆下一篇:华为OD机试真题 Java 实现【路灯照明问题】【2022Q4 100分】,感谢fly晨发现这个问题,并提供更优质的算法
🏆本文收录于,华为OD机试(JAVA)真题(A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。