【leetcode 496 題目】
給定兩個沒有重複元素的數組 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每個元素在 nums2 中的下一個比其大的值。 nums1 中數字 x 的下一個更大元素是指 x 在 nums2 中對應位置的右邊的第一個比 x 大的元素。如果不存在,對應位置輸出-1。 示例 1: 輸入: nums1 = [4,1,2], nums2 = [1,3,4,2]. 輸出: [-1,3,-1] 解釋: 對於num1中的數字4,你無法在第二個數組中找到下一個更大的數字,因此輸出 -1。 對於num1中的數字1,第二個數組中數字1右邊的下一個較大數字是 3。 對於num1中的數字2,第二個數組中沒有下一個更大的數字,因此輸出 -1。 示例 2: 輸入: nums1 = [2,4], nums2 = [1,2,3,4]. 輸出: [3,-1] 解釋: 對於num1中的數字2,第二個數組中的下一個較大數字是3。 對於num1中的數字4,第二個數組中沒有下一個更大的數字,因此輸出 -1。 注意: nums1和nums2中所有元素是唯一的。 nums1和nums2 的數組大小都不超過1000。
【leetcode 503 題目】
給定一個循環數組(最後一個元素的下一個元素是數組的第一個元素),輸出每個元素的下一個更大元素。 數字 x 的下一個更大的元素是按數組遍歷順序,這個數字之後的第一個比它更大的數, 這意味着你應該循環地搜索它的下一個更大的數。如果不存在,則輸出 -1。 示例 1: 輸入: [1,2,1] 輸出: [2,-1,2] 解釋: 第一個 1 的下一個更大的數是 2; 數字 2 找不到下一個更大的數; 第二個 1 的下一個最大的數需要循環搜索,結果也是 2。 注意: 輸入數組的長度不會超過 10000。
【分析】
從題目中我們可以看出,496題和503題都是尋找每一個元素的下一個更大的元素,不同的是:在496題中,只需要遍歷數組一遍,而且數組中的元素是不可重複的,而503題中數組是循環數組,意味着可以循環遍歷,而且題目中沒有指出數組元素不可重複。
我在分析這兩個題目的時候都使用了單調棧的方法,下面是具體的分析過程。
【496題】
總體思想:忽略數組 nums1,先對將 nums2 中的每一個元素,求出其下一個更大的元素。隨後對於將這些答案放入哈希映射(HashMap)中,再遍歷數組 nums1,並直接找出答案。對於 nums2,我們可以使用單調棧來解決這個問題。
- 把第一個元素 nums2[1] 放入棧,
- 對於第二個元素 nums2[2],如果 nums2[2] > nums2[1],那麼我們就找到了 nums2[1] 的下一個更大元素 nums2[2],此時就可以把 nums2[1] 出棧並把 nums2[2] 入棧;如果 nums2[2] <= nums2[1],我們就僅把 nums2[2] 入棧。
- 對於第三個元素 nums2[3],此時棧中有若干個元素,那麼所有比 nums2[3] 小的元素都找到了下一個更大元素(即 nums2[3]),因此可以出棧,在這之後,我們將 nums2[3] 入棧,以此類推。
可以發現,我們維護了一個單調棧,棧中的元素從棧頂到棧底是單調不降的。當我們遇到一個新的元素 nums2[i] 時,我們判斷棧頂元素是否小於 nums2[i],如果是,那麼棧頂元素的下一個更大元素即爲 nums2[i],我們將棧頂元素出棧。重複這一操作,直到棧爲空或者棧頂元素大於 nums2[i]。此時我們將 nums2[i] 入棧,保持棧的單調性,並對接下來的 nums2[i + 1], nums2[i + 2] ... 執行同樣的操作。那麼,由於數組中的元素不重複,則不同元素對應的下一個更大元素都可以在hash表中尋找到。
【503題】
總體思想:和496題相似,維護一個單調棧(單調遞增棧),同時創建一個hash表,但是在hash表中存放的是索引值,這樣就可以避免重複元素導致的結果錯誤。
重要一點:需要將兩個相同的數組拼接成一個數組,相當於循環數組了。
【Python代碼:496】
class Solution:
#暴力解法 256m
def nextGreaterElement1(self, nums1: list, nums2: list) -> list:
nums1_length = len(nums1)
nums2_length = len(nums2)
result = []
for i in range(nums1_length):
for j in range(nums2_length):
if nums2[j] == nums1[i]:
k = j + 1
flag = 0
while k < nums2_length:
if nums2[k] > nums1[i]:
flag = 1
result.append(nums2[k])
break
else:
k += 1
if flag == 0:
result.append(-1)
break
return result
#單調棧解法 56m
def nextGreaterElement(self, nums1: list, nums2: list) -> list:
hash_nums2 = {}
stack_nums2 = []
result = []
stack_nums2.append(nums2[0])
if len(nums1) == 0 or len(nums2) == 0:
return result
for i in range(1,len(nums2)): #維護一個單調遞增棧,當前元素大於棧頂元素時將鍵值對存入hash表中,將棧頂元素出棧,並將當前元素入棧,如果當前元素小於棧頂元素則將當前元素入棧
if nums2[i] <= stack_nums2[-1]:
stack_nums2.append(nums2[i])
else:
while len(stack_nums2) != 0 and nums2[i] > stack_nums2[-1]:
hash_nums2[stack_nums2[-1]]=nums2[i]
stack_nums2.pop()
stack_nums2.append(nums2[i])
if len(stack_nums2) != 0:
for i in stack_nums2:
hash_nums2[i] = -1
for i in nums1:
result.append(hash_nums2[i])
return result
s = Solution()
nums1 = [4,1,2]
nums2 = [1,3,4,2]
print(s.nextGreaterElement(nums1,nums2))
【Python代碼 503】
class Solution:
def nextGreaterElements(self, nums: list) -> list:
nums_new = []
i = 0
while i < 2:
for j in nums:
nums_new.append(j)
i += 1
hash_nums = {}
stack_nums = []
index_nums = []
result = []
stack_nums.append(nums[0])
index_nums.append(0)
for i in range(1,len(nums_new)):
if nums_new[i] <= stack_nums[-1]:
stack_nums.append(nums_new[i])
index_nums.append(i)
else:
while len(stack_nums) != 0 and nums_new[i] > stack_nums[-1]:
hash_nums[index_nums[-1]] = nums_new[i]
stack_nums.pop()
index_nums.pop()
stack_nums.append(nums_new[i])
index_nums.append(i)
if len(index_nums) != 0:
for i in index_nums:
hash_nums[i] = -1
for i in range(len(nums)):
result.append(hash_nums[i])
return result
s = Solution()
nums = [100,1,11,1,120,111,123,1,-1,-100]
print(s.nextGreaterElements(nums))