Leetcode题hash table medium 3/18/36/49/94/138/166/187/274/299,Python多种解法(十一)

前文

  继上篇hash table的easy篇,本篇继续分享hash table的medium篇。

3. Longest Substring Without Repeating Characters



class Solution(object):
    """
    用传统的dict来完成,不在时加入,在时进行判断:首先判断是否当前的下标差为最大值,接着需要判断下标的起始点更新,
    比如'abcdbce',前四个正常录入dict,而到了下标4也就是'b'时,因为'b'在dict里面,所以start从0变成2也就是'c'的位置,
    因为接下来不重复的肯定是从c开始计数了,直到又碰到c,此时下标就从2变成6,for也循环结束了,然后返回最大值
    Runtime: 80 ms, faster than 37.09% of Python online submissions for Longest Substring Without Repeating Characters.
    Memory Usage: 12.3 MB, less than 9.40% of Python online submissions for Longest Substring Without Repeating Characters.
    """
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        dic, res, start, = {}, 0, 0
        for i, ch in enumerate(s):
            if ch in dic:
                # update the res
                res = max(res, i-start)
                # here should be careful, like "abba"
                start = max(start, dic[ch]+1)
            dic[ch] = i
        # return should consider the last
        # non-repeated substring
        return max(res, len(s)-start)
18. 4Sum
import collections
import itertools


class Solution(object):
    """
    直接沿用3Sum的解法,多添加一层罢了,所以效率也是低的不行,不过这种方法算是最容易想出的。
    Runtime: 808 ms, faster than 22.63% of Python online submissions for 4Sum.
    Memory Usage: 10.7 MB, less than 100.00% of Python online submissions for 4Sum.
    """
    def fourSum(self, nums, target):
        nums.sort()
        ans = []
        for a in range(len(nums)-3):
            if a > 0 and nums[a] == nums[a-1]:
                continue
            for b in range(a+1,len(nums)-2):
                if b > a+1 and nums[b] == nums[b-1]:
                    continue
                c, d = b+1, len(nums)-1
                while c < d:
                    tot = nums[a]+nums[b]+nums[c]+nums[d]
                    if tot == target:
                        ans.append([nums[a],nums[b],nums[c],nums[d]])
                    if tot <= target:
                        c += 1
                        while nums[c] == nums[c-1] and c < d:
                            c += 1
                    if tot >= target:
                        d -= 1
                        while nums[d] == nums[d+1] and c < d:
                            d -= 1
        return ans


class Solution2(object):
    """
    这里采用python的高级解法,这些用法看的我眼花缭乱,感觉自己学了一个假python;
    通过defaultdict建立字典,可以在key不存在时不报错,而是默认value为list即空列表;
    用combinations找出所有的index、value能构成的二元元祖;
    接着遍历two_sum的key,也就是nums任意两个数的和,因为value是set,所以接下来都是围绕set的操作;
    set.isdisjoint是求交集,即两个set没有相同的部分返回真,所以完美规避了两个pair相同;
    pair1|pair2则是求并集,即两个set的所有元素,;
    这里的sorted也是必备的,需要把不同的索引但是重复的数字给删除了;
    关于del two_sum[t],也可以不删除,因为去掉这句代码照常运行,不过速度会慢点,这点还不清楚原因。
    Runtime: 168 ms, faster than 70.47% of Python online submissions for 4Sum.
    Memory Usage: 23.5 MB, less than 100.00% of Python online submissions for 4Sum.
    """
    def fourSum(self, nums, target):
        two_sum = collections.defaultdict(list)
        res = set()
        for (n1, i1), (n2, i2) in itertools.combinations(enumerate(nums), 2):
            two_sum[i1+i2].append({n1, n2})
        for t in list(two_sum.keys()):
            if not two_sum[target-t]:
                continue
            for pair1 in two_sum[t]:
                for pair2 in two_sum[target-t]:
                    if pair1.isdisjoint(pair2):
                        res.add(tuple(sorted(nums[i] for i in pair1 | pair2)))
            del two_sum[t]
        return [list(r) for r in res]
36. Valid Sudoku




class Solution(object):
    """
    直接按题目大意,从横、竖、9宫格三方面来比较
    比较有意思的是9宫格的取得方式(每次取一个小九宫格),另外比较的话直接定义字典(或集合)来存储,存在的话则说明有重复值
    Runtime: 84 ms, faster than 34.44% of Python online submissions for Valid Sudoku.
    Memory Usage: 11.7 MB, less than 5.11% of Python online submissions for Valid Sudoku.
    """
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        for i in range(9):
            if not self.isValidNine(board[i]):
                return False
            col = [c[i] for c in board]
            if not self.isValidNine(col):
                return False
        for i in [0, 3, 6]:
            for j in [0, 3, 6]:
                block = [board[s][t] for s in [i, i+1, i+2] for t in [j, j+1, j+2]]
                if not self.isValidNine(block):
                    return False
        return True

    def isValidNine(self, row):
        map = {}
        for c in row:
            if c != '.':
                if c in map:
                    return False
                else:
                    map[c] = True
        return True





class Solution2(object):
    """
    可以说是上面的简化版,不过相对没那么好理解
    Runtime: 76 ms, faster than 42.37% of Python online submissions for Valid Sudoku.
    Memory Usage: 11.8 MB, less than 5.11% of Python online submissions for Valid Sudoku.
    """
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        seen = set()
        return not any(x in seen or seen.add(x)
                       for i, row in enumerate(board)
                       for j, c in enumerate(row)
                       if c != '.'
                       for x in ((c, i), (j, c), (i/3, j/3, c)))


class Solution3(object):
    """
    相对上面一种简化版,这个版本更好理解
    Runtime: 80 ms, faster than 40.20% of Python online submissions for Valid Sudoku.
    Memory Usage: 11.9 MB, less than 5.11% of Python online submissions for Valid Sudoku.
    """
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        seen = []
        for i, row in enumerate(board):
            for j, c in enumerate(row):
                if c != '.':
                    seen += [(c,j),(i,c),(i/3,j/3,c)]
        return len(seen) == len(set(seen))

49. Group Anagrams



class Solution(object):
    """
    建立有序字典,比对每一个排序后的值,如果数值相同,则加入到dict的value里,
    最后再对dict.value进行排序,返回列表即可
    Runtime: 96 ms, faster than 92.77% of Python online submissions for Group Anagrams.
    Memory Usage: 17.5 MB, less than 5.13% of Python online submissions for Group Anagrams
    """
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        groups = collections.defaultdict(list)
        for s in strs:
            groups[tuple(sorted(s))].append(s)
        return list(map(sorted, groups.values()))

94. Binary Tree Inorder Traversal
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution1(object):
    """
    中序遍历,即先获取左子树的结果,再根节点,再右子树,思路还是很清晰
    Runtime: 12 ms, faster than 99.66% of Python online submissions for Binary Tree Inorder Traversal.
    Memory Usage: 11.8 MB, less than 5.78% of Python online submissions for Binary Tree Inorder Traversal.
    """
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        self.helper(root, res)
        return res

    def helper(self, root, res):
        if root:
            self.helper(root.left, res)
            res.append(root.val)
            self.helper(root.right, res)


class Solution2(object):
    """
    iteratively,即用迭代的思路来完成该题,整体和上述差别不大
    Runtime: 16 ms, faster than 98.85% of Python online submissions for Binary Tree Inorder Traversal.
    Memory Usage: 11.8 MB, less than 5.78% of Python online submissions for Binary Tree Inorder Traversal.
    """
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res,stack = [],[]
        while True:
            while root:
                stack.append(root)
                root = root.left
            if not stack:
                return res
            node = stack.pop()
            res.append(node.val)
            root = node.right
138. Copy List with Random Pointer
# Definition for a Node.
class Node(object):
    def __init__(self, val, next, random):
        self.val = val
        self.next = next
        self.random = random

class Solution(object):
    """
    先构造字典,将老链表和新链表一一对应,这样就构造了一个纯next的链表,然后再循环即可
    Runtime: 392 ms, faster than 33.67% of Python online submissions for Copy List with Random Pointer.
    Memory Usage: 14.6 MB, less than 100.00% of Python online submissions for Copy List with Random Pointer.
    """
    def copyRandomList(self, head):
        """
        :type head: Node
        :rtype: Node
        """
        nodeDict = dict()
        dummy = Node(0, None, None)
        nodeDict[head] = dummy
        newHead, pointer = dummy, head
        while pointer:
            node = Node(pointer.val, pointer.next, None)
            nodeDict[pointer] = node
            newHead.next = node
            newHead, pointer = newHead.next, pointer.next
        pointer = head
        while pointer:
            if pointer.random:
                nodeDict[pointer].random = nodeDict[pointer.random]
            pointer = pointer.next
        return dummy.next


166. Fraction to Recurring Decimal



class Solution(object):
    """
    Runtime: 36 ms, faster than 7.30% of Python online submissions for Fraction to Recurring Decimal.
    Memory Usage: 11.9 MB, less than 5.55% of Python online submissions for Fraction to Recurring Decimal.
    """
    def fractionToDecimal(self, numerator, denominator):
        """
        :type numerator: int
        :type denominator: int
        :rtype: str
        """
        # divmod获取整除后的整数和余数
        n, remainder = divmod(abs(numerator), abs(denominator))
        # sign判断是否有负数,作为符号展示
        sign = '-' if numerator*denominator < 0 else ''
        result = [sign+str(n), '.']
        stack = []
        # 循环判断余数是否开始循环
        while remainder not in stack:
            stack.append(remainder)
            n, remainder = divmod(remainder*10, abs(denominator))
            result.append(str(n))

        idx = stack.index(remainder)
        result.insert(idx+2, '(')
        result.append(')')
        return ''.join(result).replace('(0)', '').rstrip('.')
187. Repeated DNA Sequences


class Solution(object):
    """
    直接依次遍历取值,判断是否存在定义的dict里,存在就val+1,不存在就为1,最后遍历取值val>1的
    Runtime: 72 ms, faster than 58.05% of Python online submissions for Repeated DNA Sequences.
    Memory Usage: 30.4 MB, less than 52.31% of Python online submissions for Repeated DNA Sequences.
    """
    def findRepeatedDnaSequences(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        dict1 = {}
        for i,v in enumerate(s[:-9]):
            dict1[s[i:i+10]] = dict1.get(s[i:i+10],0) + 1
        return [k for k,v in dict1.iteritems() if v>1]


class Solution2(object):
    """
    用Counter来简化第一步行程dict的操作,并且效率也变高了
    Runtime: 68 ms, faster than 63.86% of Python online submissions for Repeated DNA Sequences.
    Memory Usage: 35 MB, less than 15.66% of Python online submissions for Repeated DNA Sequences
    """
    def findRepeatedDnaSequences(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        from collections import Counter
        return [k for k,v in Counter([s[x:x+10] for x in range(len(s)-9)]).iteritems() if v > 1]
274. H-Index
class Solution(object):
    """
    先排序再计算
    Runtime: 24 ms, faster than 65.02% of Python online submissions for H-Index.
    Memory Usage: 11.9 MB, less than 47.22% of Python online submissions for H-Index.
    """
    def hIndex(self, citations):
        """
        :type citations: List[int]
        :rtype: int
        """
        N = len(citations)
        citations.sort()
        h = 0
        for i, c in enumerate(citations):
            h = max(h, min(N - i, c))
        return h

299. Bulls and Cows
class Solution(object):
    """
    先逐一匹配看是否相等,然后算出两个列表的长度最小值,最后获取bull和cow的个数
    Runtime: 24 ms, faster than 99.74% of Python online submissions for Bulls and Cows.
    Memory Usage: 11.7 MB, less than 85.37% of Python online submissions for Bulls and Cows.
    """
    def getHint(self, secret, guess):
        """
        :type secret: str
        :type guess: str
        :rtype: str
        """
        bulls = sum(map(operator.eq, secret, guess))
        both = sum(min(secret.count(x), guess.count(x)) for x in set(guess))
        return '%dA%dB' % (bulls, both - bulls)

总结

  感觉hash table的medium题后面的题意比较难理解,整体相对easy要难一些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值