leetcode刷题记录211-220 python版

前言

继续leetcode刷题生涯
这里记录的都是笔者觉得有点意思的做法
参考了好几位大佬的题解,尤其是powcai大佬和labuladong大佬,感谢各位大佬

211. 添加与搜索单词 - 数据结构设计

class WordDictionary:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        from collections import defaultdict
        self.lookup = {}
    def addWord(self, word: str) -> None:
        """
        Adds a word into the data structure.
        """
        tree = self.lookup
        for a in word:
            tree = tree.setdefault(a,{})
        tree["#"] = {}
    def search(self, word: str) -> bool:
        """
        Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
        """
        def helper(word, tree):
            if not word:
                if "#" in tree:
                    return True
                return False
            if word[0] == ".":
                for t in tree:
                    if helper(word[1:], tree[t]):
                        return True
            elif word[0] in tree:
                if helper(word[1:],tree[word[0]]):
                    return True
            return False
        return helper(word, self.lookup)

212. 单词搜索 II

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        lookup = {}
        # word存入前缀树
        for word in words:
            t = lookup
            for a in word:
                t = t.setdefault(a, {})
            t["end"] = 1
        res = []
        row = len(board)
        col = len(board[0])
        # dfs
        def dfs(i, j, lookup, s):
            c = board[i][j]
            if c not in lookup:
                return
            lookup = lookup[c]
            if "end" in lookup and lookup["end"] == 1:
                res.append(s+c)
                lookup["end"] = 0
            board[i][j] = "#"
            for x,y in [[-1,0], [1,0], [0,-1],[0,1]]:
                tmp_i = x + i
                tmp_j = y + j
                if 0 <= tmp_i < row and 0 <= tmp_j < col and board[tmp_i][tmp_j] != "#":
                    dfs(tmp_i, tmp_j, lookup, s + c)
            board[i][j] = c
        for i in range(row):
            for j in range(col):
                dfs(i, j, lookup, "")
        return res

213. 打家劫舍 II

# 问题分成求 nums[0:n - 1]或者 nums[1:n]
class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums: return 0
        if len(nums) == 1: return nums[0]
        def helper(nums):
            if not nums: return 0
            if len(nums) == 1: return nums[0]
            n = len(nums)
            dp = [0] * (n+1)
            dp[1] = nums[0]
            for i in range(2, n+1):
                dp[i] = max(dp[i-1], dp[i-2]+nums[i-1])
            return dp[-1]
        return max(helper(nums[1:]), helper(nums[:-1]))

214. 最短回文串

# 暴力 O(n^2)
class Solution:
    def shortestPalindrome(self, s: str) -> str:
       r = s[::-1]
       for i in range(len(s) + 1):
           if s.startswith(r[i:]):
               return r[:i] + s
# KMP O(n)
class Solution:
    def shortestPalindrome(self, s: str) -> str:
        def get_table(p):
            table = [0] * len(p)
            i, j = 1, 0
            while i < len(p):
                if p[i] == p[j]:
                    j += 1
                    table[i] = j
                    i += 1
            	else:
               		if j > 0:
                    		j = table[j-i]
                	else:
                    		i += 1
                    		j = 0
            return table
        table = get_table(s + "#" + s[::-1])
        return s[table[-1]:][::-1] + s

215. 数组中的第K个最大元素

# 普通排序 nlogn
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        return sorted(nums, reverse=True)[k-1]
# 堆排序 klogn
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        import heapq
        return heapq.nlargest(k, nums)[-1]
# 手写堆排序
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        def adjust_heap(idx, max_len):
            left = 2 * idx + 1
            right = 2 * idx + 2
            max_loc = idx
            if left < max_len and nums[max_loc] < nums[left]:
                max_loc = left
            if right < max_len and nums[max_loc] < nums[right]:
                max_loc = right
            if max_loc != idx:
                nums[idx], nums[max_loc] = nums[max_loc], nums[idx]
                adjust_heap(max_loc, max_len)
            # 建堆
        n = len(nums)
        for i in range(n // 2 - 1, -1, -1):
            adjust_heap(i, n)
        # print(nums)
        res = None
        for i in range(1, k + 1):
            # print(nums)
            res = nums[0]
            nums[0], nums[-i] = nums[-i], nums[0]
            adjust_heap(0, n - i)
        return res
# 快排 O(n)最差O(n^2)
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        def partition(left, right):
            pivot = nums[left]
            l = left + 1
            r = right
            while l <= r:
                if nums[l] < pivot and nums[r] > pivot:
                    nums[l], nums[r] = nums[r], nums[l]
                if nums[l] >= pivot:
                    l += 1
                if nums[r] <= pivot:
                    r -= 1
            nums[r], nums[left] = nums[left], nums[r]
            return r
        left = 0
        right = len(nums) - 1
        while 1:
            idx = partition(left, right)
            if idx == k - 1:
                return nums[idx]
            if idx < k - 1:
                left = idx + 1
            if idx > k - 1:
                right = idx - 1

216. 组合总和 III

# 回溯
class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        if n <= 0 or n > (k * 9): return []
        res = []
        def helper(k, n, start, tmp):
            if k == 0:
                if n == 0:
                    res.append(tmp)
                return
            for i in range(start, 10):
                if n - i < 0: break
                helper(k - 1, n - i, i + 1, tmp + [i])
        helper(k, n, 1, [])
        return res
# 库函数
class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        import itertools
        return [item for item in itertools.combinations(range(1, 10), k) if sum(item) == n]

217. 存在重复元素

# 集合
class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        s = set(nums)
        if len(s) != len(nums):
            return True
        return False

218. 天际线问题

# 分而治之
class Solution:
    def getSkyline(self, buildings: List[List[int]]) -> List[List[int]]:
        if not buildings: return []
        if len(buildings) == 1:
            return [[buildings[0][0], buildings[0][2]], [buildings[0][1], 0]]
        mid = len(buildings) // 2
        left = self.getSkyline(buildings[:mid])
        right = self.getSkyline(buildings[mid:])
        return self.merge(left, right)
    def merge(self, left, right):
        lh = rh = 0
        l = r = 0
        res = []
        while l < len(left) and r < len(right):
            if left[l][0] < right[r][0]:
                cp = [left[l][0], max(left[l][1], rh)]
                lh = left[l][1]
                l += 1
            elif left[l][0] > right[r][0]:
                cp = [right[r][0], max(right[r][1], lh)]
                rh = right[r][1]
                r += 1
            else:
                cp = [left[l][0], max(left[l][1], right[r][1])]
                lh = left[l][1]
                rh = right[r][1]
                l += 1
                r += 1
            if len(res) == 0 or res[-1][1] != cp[1]:
                res.append(cp)
        res.extend(left[l:] or right[r:])
        return res

219. 存在重复元素 II

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        if len(set(nums)) == len(nums):
            return False
        lookup = {}
        for index, num in enumerate(nums):
            if num in lookup and index-lookup[num] <= k:
                return True
            lookup[num] = index
        return False

220. 存在重复元素 III

class Solution:
    def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
        if t < 0: return False
        n = len(nums)
        d = {}
        w = t + 1
        for i in range(n):
            m = nums[i] // w
            if m in d:
                return True
            if m - 1 in d and abs(nums[i] - d[m - 1]) < w:
                return True
            if m + 1 in d and abs(nums[i] - d[m + 1]) < w:
                return True
            d[m] = nums[i]
            if i >= k: del d[nums[i - k] // w]
        return False

你可能感兴趣的:(leetcode)