题目
有 n 个人排成一个队列,从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights ,每个整数 互不相同,heights[i] 表示第 i 个人的高度。
一个人能 看到 他右边另一个人的条件是这两人之间的所有人都比他们两人 矮 。更正式的,第 i 个人能看到第 j 个人的条件是 i < j 且 min(heights[i], heights[j]) > max(heights[i+1], heights[i+2], ..., heights[j-1]) 。
请你返回一个长度为 n 的数组 **answer **,其中 **answer[i] **是第 i 个人在他右侧队列中能 看到 的 人数 。
解题方式一
/**
* @param {number[]} heights
* @return {number[]}
*/
var canSeePersonsCount = function (heights) {
let target = [];
heights.map((item, index, arr) => {
const other = arr.slice(index + 1);
let i = 0;
other.map((piece, pIndex, pArr) => {
const pIndex1 = arr.findIndex(j => j == piece)
const middle = arr.slice(index + 1, pIndex1);
if (Math.min(item, piece) > Math.max.apply(null, middle)) {
i++;
}
});
target.push(i)
});
return target
};
将目标数组heights遍历,每一项为item,截取出每一项后面的数组项,组成新数组other, 遍历other,每一项为piece, 找到item和piece中间项组成的数组middle,然后Math.min(item, piece) > Math.max.apply(null, middle),则 item可以看到piece,i++
这种解法,在数组长度很大时,很消耗性能
更好的解法
/**
* @param {number[]} heights
* @return {number[]}
*/
var canSeePersonsCount = function (heights) {
const n = heights.length;
const res = new Array(n).fill(0);
// 保证栈中为递增
const stack = [];
// 放最后项的索引
stack.unshift(n - 1);
// 从右向左遍历
for (let i = n - 2; i >= 0; i--) {
// 栈顶元素比当前元素矮
while (stack.length && heights[i] > heights[stack[0]]) {
// 从头部移出下标,后续左侧的人看不到此编号
stack.shift();
// 可见人数增加
res[i]++;
}
// 栈中还有元素,那么栈顶元素比当前人员高,到此终止,后续人员看不到
if (stack.length > 0) {
res[i]++;
}
// 在头部加入下标
stack.unshift(i);
}
return res;
};
上面的写法性能更好,在大数组的情况下,执行的速度很快。