🚀 算法题 🚀 |
🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀
🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨
🌲 作者简介:硕风和炜,CSDN-Java领域优质创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎
🌲 恭喜你发现一枚宝藏博主,赶快收入囊中吧🌻
🌲 人生如棋,我愿为卒,行动虽慢,可谁曾见我后退一步?🎯🎯
🚀 算法题 🚀 |
🚩 题目链接
⛲ 题目描述
给你一个下标从 0 开始的正整数数组 heights ,其中 heights[i] 表示第 i 栋建筑的高度。
如果一个人在建筑 i ,且存在 i < j 的建筑 j 满足 heights[i] < heights[j] ,那么这个人可以移动到建筑 j 。
给你另外一个数组 queries ,其中 queries[i] = [ai, bi] 。第 i 个查询中,Alice 在建筑 ai ,Bob 在建筑 bi 。
请你能返回一个数组 ans ,其中 ans[i] 是第 i 个查询中,Alice 和 Bob 可以相遇的 最左边的建筑 。如果对于查询 i ,Alice 和 Bob 不能相遇,令 ans[i] 为 -1 。
示例 1:
输入:heights = [6,4,8,5,2,7], queries = [[0,1],[0,3],[2,4],[3,4],[2,2]]
输出:[2,5,-1,5,2]
解释:第一个查询中,Alice 和 Bob 可以移动到建筑 2 ,因为 heights[0] < heights[2] 且 heights[1] < heights[2] 。
第二个查询中,Alice 和 Bob 可以移动到建筑 5 ,因为 heights[0] < heights[5] 且 heights[3] < heights[5] 。
第三个查询中,Alice 无法与 Bob 相遇,因为 Alice 不能移动到任何其他建筑。
第四个查询中,Alice 和 Bob 可以移动到建筑 5 ,因为 heights[3] < heights[5] 且 heights[4] < heights[5] 。
第五个查询中,Alice 和 Bob 已经在同一栋建筑中。
对于 ans[i] != -1 ,ans[i] 是 Alice 和 Bob 可以相遇的建筑中最左边建筑的下标。
对于 ans[i] == -1 ,不存在 Alice 和 Bob 可以相遇的建筑。
示例 2:
输入:heights = [5,3,8,2,6,1,4,6], queries = [[0,7],[3,5],[5,2],[3,0],[1,6]]
输出:[7,6,-1,4,6]
解释:第一个查询中,Alice 可以直接移动到 Bob 的建筑,因为 heights[0] < heights[7] 。
第二个查询中,Alice 和 Bob 可以移动到建筑 6 ,因为 heights[3] < heights[6] 且 heights[5] < heights[6] 。
第三个查询中,Alice 无法与 Bob 相遇,因为 Bob 不能移动到任何其他建筑。
第四个查询中,Alice 和 Bob 可以移动到建筑 4 ,因为 heights[3] < heights[4] 且 heights[0] < heights[4] 。
第五个查询中,Alice 可以直接移动到 Bob 的建筑,因为 heights[1] < heights[6] 。
对于 ans[i] != -1 ,ans[i] 是 Alice 和 Bob 可以相遇的建筑中最左边建筑的下标。
对于 ans[i] == -1 ,不存在 Alice 和 Bob 可以相遇的建筑。
提示:
1 <= heights.length <= 5 * 104
1 <= heights[i] <= 109
1 <= queries.length <= 5 * 104
queries[i] = [ai, bi]
0 <= ai, bi <= heights.length - 1
🌟 求解思路&实现代码&运行结果
⚡ 单调栈
🥦 求解思路
- 根据题目的意思,想要找到下一个更大的元素,需要我们维护一个单调递减的栈,然后根据给定的queries数组进行查询。
- 具体求解算法如下:
- 先根据heights数组求得next数组,求下一个更大的元素
- 根据queries数组查询,ans做记录,因为每一个查询左右边界的大小不确定,先确定去区间和右区间
- 如果left == right , 直接返回ans[i]=left;
- 然后分别查询left的下一个更大的元素和right下一个更大的元素;
- 如果next[left] == -1 或者 next[right] = -1,直接返回-1;
- 否则,如果此时heights[left] < heights[right],设置ans[i] = right;
- 如果heights[left] > heights[right],判断此时next[left] 是否大于right,如果大于,直接更新ans[i] = next[left],否则,从right + 1开始循环判断,如果此时的高度大于heights[left],直接更新ans[i] =
当前位置
,直接结束; - 返回最终的ans数组。
- 有了基本的思路,接下来我们就来通过代码来实现一下的解法。
🥦 实现代码
class Solution {
public int[] leftmostBuildingQueries(int[] heights, int[][] queries) {
int n = heights.length, m = queries.length;
int[] ans = new int[m];
Arrays.fill(ans, -1);
Deque<Integer> queue = new LinkedList<>();
int[] next = new int[n];
Arrays.fill(next, -1);
for (int i = 0; i < n; i++) {
while (!queue.isEmpty() && heights[queue.peekLast()] < heights[i]) {
int j = queue.pollLast();
next[j] = i;
}
queue.addLast(i);
}
for (int i = 0; i < m; i++) {
int a = queries[i][0], b = queries[i][1];
int left = Math.min(a, b);
int right = Math.max(a, b);
int nextA = next[left], nextB = next[right];
if(left == right){
ans[i] = left;
continue;
}
if (nextA == -1) {
continue;
}
if (heights[left] < heights[right]) {
ans[i] = right;
} else {
if (nextB == -1) {
continue;
} else {
if (nextA > right) {
ans[i] = nextA;
} else {
for (int j = right + 1; j < n; j++) {
if (heights[j] > heights[left]) {
ans[i] = j;
break;
}
}
}
}
}
}
return ans;
}
}
🥦 运行结果
💬 共勉
最后,我想和大家分享一句一直激励我的座右铭,希望可以与大家共勉! |