堆栈方法以查找最快的每日温度

时间:2019-04-16 00:59:16

标签: python

我正在Daily Temperatures - LeetCode

  
      
  1. 每日温度
  2.   
     

给出每日温度列表T,返回一个列表,以便对于输入中的每一天,告诉您要等到温暖的温度需要多少天。如果没有将来的可能,请放0

     

例如,给定温度列表T = [73, 74, 75, 71, 69, 72, 76, 73],您的输出应为[1, 1, 4, 2, 1, 1, 0, 0]

     

注意temperatures的长度将在[1, 30000]范围内。每个温度都是

范围内的整数

分析问题

    Given:nums, list a daily temperature, len(nums) < 30000, in range[30, 100]
    Find:How many days to wait until a warmmer temperature, soonest 
    Requirements: if empty return 0, 

具有两个指针(O(n ** 2))的蛮力解决方案

class Solution1:
    def dailyTperatures(self, nums: 'List[int]') -> 'List[int]':
        res = [0] * len(nums)
        for i in range(len(nums)):
            for j in range(i, len(nums)):
                if nums[j] > nums[i]:
                    res[i] = j - i 
                    break #guarentee the soonest 
        return res  

重新检查问题,发现没有使用给定条件range[30,100]

官方答案利用了这种情况

计划是使用next array来存储(记住)温度更高的索引。

class Solution2:
    def dailyTemperatures(self, nums):
        """
        Runtime: 976 ms, faster than 8.40%
        Memory Usage: 16.6 MB, less than 11.02% 
        """
        nxt = [float('inf')] * 102
        res = [0] * len(nums)
        for i in range(len(nums) - 1, -1, -1):
            #Use 102 so min(nxt[t]) has a default value
            j= min(nxt[t] for t in range(nums[i]+1, 102))
            if j< float('inf'):
                res[i] = j- i
            nxt[nums[i]] = i
        return res   

直到现在,len(nums) < 30000还剩下一个条件。我检查了所有其他解决方案,但没有发现这种情况是其中的一种用法。

正式的stack解决方案开头是一个好问题

  

考虑尝试在T[i]查找下一个较暖的事件。我们必须记住哪些信息(关于T[j]的{​​{1}})?

该想法是使用堆栈记住温度较高的索引。

j > i

具有相同想法的更优雅的解决方案。

class Solution3:
    def dailyTemperatures(self, nums):
        res = [0] * len(nums)
        stack = [] #indexes from hottest to coldest
        for i in range(len(nums) - 1, -1, -1):
            while stack and nums[i] >= nums[stack[-1]]:
                stack.pop() #remove lower and not soonest 
            if stack:
                res[i] = stack[-1] - i
            stack.append(i)
        return res       

结论:

在上述所有解决方案中,条件class Solution4: def dailyTemperatures(self, nums: 'List[int]') -> 'List[int]': """ Runtime: 300 ms, faster than 74.12% Memory Usage: 16.6 MB, less than 9.45% """ res = [0] * len(nums) stack = [] for i in range(len(nums)): while stack and nums[i] > nums[stack[-1]]: #find the higher cur = stack.pop() res[cur] = i - cur stack.append(i) return res 未得到利用。

这种情况是什么意思?

2 个答案:

答案 0 :(得分:2)

您可以使用enumerate()和index()函数在列表理解中做到这一点:

[ [t<n for n in T[i:]+[t+1]].index(True)%(len(T)-i) for i,t in enumerate(T)]

# [1, 1, 4, 2, 1, 1, 0, 0]

如果要考虑性能,那么程序方法将运行得更快:

def dailyTemps(T):
    result = [0]*len(T)
    seeking = []
    prevTemp = 0
    for i,(t0,t1) in enumerate(zip(T,T[1:])):        
        while seeking and prevTemp < t0:
            ip = seeking.pop(-1)
            result[ip] = i - ip
            if seeking: prevTemp = T[seeking[-1]]
        if t0 >= t1:
            seeking.append(i)
            prevTemp = t0
        else:
            result[i] = 1
    return result

答案 1 :(得分:1)

条件len(nums) < 30000用于告诉您数据规模。当面对不同的数据规模时,您可能会使用不同的设计策略。

例如if len(nums) < 30,蛮力可能是最好的解决方案,没有多余的空间且不够快。

您会在Leetcode中发现许多问题,这些问题也会为您提供此信息。而且您不会在代码中使用它,但会在想法中使用它。