美文网首页
Leetcode 【739、946、973】

Leetcode 【739、946、973】

作者: 牛奶芝麻 | 来源:发表于2019-06-28 15:06 被阅读0次
    题目描述:【Stack】739. Daily Temperatures
    解题思路:

    这道题是给一个温度列表,重新生成一个列表:对应位置是需要再等待多久温度才会升高超过该日的天数。

    看了下数据范围,直接暴力肯定不行。再读一下题目想到可以使用递减栈(栈中存储递减的温度)来解决。为了记录每个温度的位置,还要在栈中存储对应温度的索引,即(索引,温度)。做法如下:

    如果栈中有温度,且当前温度比栈中温度大,就出栈,当前索引减去出栈温度的索引就是对应的结果。每次比较完后,将当前温度入栈。

    举个例子:T = [73, 74, 75, 71, 69, 72, 76, 73],栈的变化是 [(0, 73)] -> [(1, 74)] (74 > 73,73 出栈,ans[0] = 1 - 0 = 1)-> [(2, 75)] (75 > 74,74 出栈,ans[1] = 2 - 1 = 1)-> [(2, 75), (3, 71)] (71 < 75,不执行操作)-> [(2, 75), (3, 71), (4, 69)] (69 < 71,不执行操作)-> [(2, 75), (5, 72)] (72 > 69 和 71,69 和 71 依次出栈,ans[4] = 5 - 4 = 1, ans[3] = 5 - 3 = 2)-> [(6, 76)](76 > 72 和 75,72 和 75 依次出栈,ans[5] = 6 - 5 = 1, ans[2] = 6 - 2 = 4)-> [(6, 76), (7, 73)](73 < 76,不执行操作),结束。最后,栈中剩下的一定是个递减序列,全部为 0 即可。可以得到结果 ans = [1, 1, 4, 2, 1, 1, 0, 0]。

    Python3 实现:
    class Solution:
        def dailyTemperatures(self, T: List[int]) -> List[int]:
            stack = []
            ans = [0] * len(T)
            for i in range(len(T)):
                while len(stack) > 0 and T[i] > stack[-1][1]:  # 当前数比栈顶数大,出栈
                    ind, _ = stack.pop()
                    ans[ind] = i - ind
                stack.append((i, T[i]))
            return ans
    

    题目描述:【Two Pointers】946. Validate Stack Sequences
    解题思路:

    这道题是给 pushed 和 popped 两个序列,判断是否 pushed 序列能够通过 pop 操作得到 popped 序列。

    只需要使用两个指针 i、j 分别指向 pushed 和 popped,如果 pushed[i] != popped[j],i 往后移,直到找到第一个能够和 popped 序列对应的 pop 位置。然后,pushed 删除当前元素 pushed[i],同时 i 向前移动一位,代表出栈。j 向后移动一位,判断下一个 pop 的位置。

    注意到如果刚开始就相同,如 pushed = [0, 1, 2],popped = [0, 2, 1],删除 pushed[0] 后索引 i 会变成 -1,因此还要加一个判断,就是如果 i < 0,让 i = 0 即可。

    Python3 实现:
    class Solution:
        def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
            i = j = 0
            while i < len(pushed) and j < len(popped):
                if pushed[i] != popped[j]:
                    i += 1
                else:
                    del pushed[i]
                    i -= 1
                    if i < 0: i = 0  # pushed和popped起始位置对应,del后i会变为-1
                    j += 1
            # 满足题意的一定是最后pushed为空且j到达了popped的末尾
            return True if len(pushed) == 0 and j == len(popped) else False
    
    print(Solution().validateStackSequences([0,1,2], [0,2,1]))  # True
    

    题目描述:【Sort、Heap】973. K Closest Points to Origin
    解题思路:

    这道题是给一些坐标,求距离原点 (0, 0) 前 K 小距离(欧氏距离)的那些坐标。

    思路很直接:先求出所有点距离原点的距离(O(n) 的复杂度),然后按照距离从小到大排序(O(nlogn) 的复杂度),最后输出前 K 个结果。总的时间复杂度为 O(nlogn)。

    为了在排序距离时记录原来坐标的位置,可以以(距离,索引)的形式一起排序,输出前 K 个结果时,就可以根据索引找到原来坐标的位置。实现代码如代码1所示:

    Python3 实现:

    代码1:

    class Solution:
        def kClosest(self, points: List[List[int]], K: int) -> List[List[int]]:
            dis = []
            ans = []
            for i, point in enumerate(points):
                dis.append((point[0]*point[0]+point[1]*point[1], i))  # (距离,索引)
            dis.sort()
            for i in range(K):
                ans.append(points[dis[i][1]])
            return ans
    

    实际上,sorted 函数可以通过指定 key 来直接定义排序规则,就不需要像代码1那样算距离的时候还要保存索引了。实现代码如代码2所示:

    代码2:

    class Solution:
        def kClosest(self, points: List[List[int]], K: int) -> List[List[int]]:
            return sorted(points, key = lambda x: x[0]**2 + x[1]**2)[:K]
    

    取前 K 小(或 K 大)个元素可以使用最小优先队列(或最大优先队列)。我们知道,优先队列不是真正的队列,它只是维护的一个堆,优先队列每次输出的是最大(或最小)的堆顶元素,而不是遵循先入先出。输出元素的时间复杂度为 O(logn)。

    可以使用 Python 中的 heapq 组件,通过调用 heapq.nsmallest(K, points, key = lambda x: x[0]**2 + x[1]**2) (取最大的 K 个元素对应函数是 heapq.nlargest(...))解决。

    但是由于建堆的过程是 O(nlogn) 级别的,因此总时间复杂度还是 O(nlogn)。实现代码如代码3所示:

    代码3:

    import heapq
    class Solution:
        def kClosest(self, points: List[List[int]], K: int) -> List[List[int]]:
            return heapq.nsmallest(K, points, key = lambda x: x[0]**2 + x[1]**2)
    

    相关文章

      网友评论

          本文标题:Leetcode 【739、946、973】

          本文链接:https://www.haomeiwen.com/subject/rubjcctx.html