LeetCode 503:下一个更大的元素|| (单调栈 or 线段树)
解题思路:
1、单调栈:因为是循环数组,因此把数组复制三遍,ans 数组复制为2倍长,维护一个单调非递增的栈,栈保存的元素是元组(a[i] , i ),如果后面的值有比栈顶元素的值大,栈顶元素出栈,更新ans[i]的值为让其出栈的值,最后返回ans数组的一半,即最终答案。
2、线段树:数组复制两遍,构建线段树,存的值是当前区间的最大值,当查询 a[i]后面是否有更大的元素时,查询线段树[i+1,i+length]的区间,如果区间最大值比a[i]大,优先访问左子树,如果左子树没有,说明一定在右子树,递归右子树;如果左子树有,递归左子树。
代码:
1 #单调栈
2 class Solution:
3 def nextGreaterElements(self, nums):
4 a = nums[:]+nums[:]+nums[:]
5 ans = [-1]*len(nums)*2
6 stack = []
7 length = len(nums)
8 for i in range(2*length):
9 while len(stack) > 0:
10 top = stack.pop()
11 stack.append(top)
12 if top[0] < a[i]:
13 ans[top[1]] = a[i]
14 _ = stack.pop()
15 else:
16 break
17 stack.append((a[i], i))
18 return ans[:length]
19
20 #线段树
21 class Node():
22 def __init__(self):
23 self.l = None
24 self.r = None
25 self.max = None
26 class Solution(object):
27 def get_bst(self,a,l,r):
28 n = Node()
29 if l==r:
30 n.max = a[l]
31 return n
32 mid = (l+r)//2
33 n.l = self.get_bst(a,l,mid)
34 n.r = self.get_bst(a,mid+1,r)
35 n.max = max(n.l.max,n.r.max)
36 return n
37 def query(self,root,a,l,r,ql,qr,x):
38 if l==r:
39 return root.max
40 #print(l,r)
41 if root.max < x:
42 return float('-inf')
43 mid = (l + r) // 2
44 if ql<=l and qr>=r:
45 if root.max >x:
46 vl = self.query(root.l,a,l,mid,ql,qr,x)
47 if vl>x:
48 return vl
49 vr = self.query(root.r,a,mid+1,r,ql,qr,x)
50 if vr>x:
51 return vr
52 else:
53 return float('-inf')
54 if ql<=mid :
55 vl = self.query(root.l,a,l,mid,ql,qr,x)
56 if vl>x:
57 return vl
58 if qr>mid:
59 vr = self.query(root.r,a,mid+1,r,ql,qr,x)
60 if vr >x:
61 return vr
62 return float('-inf')
63
64 def nextGreaterElements(self, nums):
65 if not nums:
66 return []
67 length = len(nums)
68 a = nums[:]+nums[:]
69 y = []
70 root = self.get_bst(a,0,len(a)-1)
71 for i in range(length):
72 x = self.query(root,a,0,len(a)-1,i+1,i+length-1,a[i])
73 if x==float('-inf'):
74 y.append(-1)
75 else:
76 y.append(x)
77 return y