给定一个数组,在不更改元素原始顺序的情况下,为每个元素找到数组中的下一个较小元素。
例如,假设给定的数组为4,2,1,5,3。
结果数组将为2,1,-1,3,-1。
在面试中有人问我这个问题,但是我想不到一个比平凡的O(n ^ 2)解决方案更好的解决方案。我想到的任何方法,例如,制作二叉搜索树或对数组进行排序,都会扭曲元素的原始顺序,从而导致错误的结果。
任何帮助将不胜感激。
def find_next_smaller_elements(xs): ys=[-1 for x in xs] stack=[] for i,x in enumerate(xs): while len(stack)>0 and x<xs[stack[-1]]: ys[stack.pop()]=x stack.append(i) return ys >>> find_next_smaller_elements([4,2,1,5,3]) [2, 1, -1, 3, -1] >>> find_next_smaller_elements([1,2,3,4,5]) [-1, -1, -1, -1, -1] >>> find_next_smaller_elements([5,4,3,2,1]) [4, 3, 2, 1, -1] >>> find_next_smaller_elements([1,3,5,4,2]) [-1, 2, 4, 2, -1] >>> find_next_smaller_elements([6,4,2]) [4, 2, -1]
之所以可行,是因为每当我们将一个项目添加到堆栈中时,我们就知道它的值已经大于或等于堆栈中的每个元素。当我们访问数组中的一个元素时,我们知道如果它比堆栈中的 任何 项目都低,则它必须比堆栈中的 最后一个 项目低,因为最后一个项目必须最大。因此,我们无需在堆栈上进行任何类型的搜索,只需考虑最后一项即可。
注意:只要添加最后一步以清空堆栈,并使用每个剩余的索引将相应的输出数组元素设置为-1,就可以跳过初始化步骤。在Python中创建时将其初始化为-1s更加容易。
这是O(N)。主循环清楚地访问每个索引一次。每个索引仅一次添加到堆栈中,一次最多删除一次。
这种问题在面试中可能会令人生畏,但我想指出,(希望)面试官不会期望解决方案能从您的头脑中完全形成。在您的思考过程中与他们交谈。我的事情是这样的:
即使您没有提出有效的算法,也要尝试让面试官了解您的想法。通常,思考过程比他们感兴趣的答案要多。对于一个棘手的问题,如果找不到最佳的解决方案但对问题有深刻的了解,可能比知道罐头的答案但不能给予太多帮助更好。分析。