hash_table-special

目录:
  • 36、 Valid Sudoku

36. Valid Sudoku

Determine if a Sudoku is valid
The Sudoku board could be partially filled, where empty cells are filled with the character
A partially filled sudoku which is valid.
Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.

判断一个数独矩阵是否有效,判断的标准是看每行每列是否有重复数字以及每个九宫格是否有重复数字。

class Solution(object):
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        m, n = len(board), len(board[0])
        if m != 9 or n != 9:
            return False
        a = set()
        for i in xrange(9):
            a.clear()
            for item in board[i]:
                if item == '.':
                    continue
                if item not in a:
                    a.add(item)
                else:
                    return False
        
        for i in xrange(9):
            temp = [ board[j][i] for j in xrange(9) ]
            a.clear()
            for item in temp:
                if item == '.':
                    continue
                if item not in a:
                    a.add(item)
                else:
                    return False
        for m in [0,3,6]:
            for n in [0,3,6]:
                temp = [ board[i][j] for i in [m,m+1,m+2] for j in [n,n+1,n+2] ]
                a.clear()
                for item in temp:
                    if item == '.':
                        continue
                    if item not in a:
                        a.add(item)
                    else:
                        return False
        return True

上述解法还是过于繁琐,不够简练

class Solution(object):
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        for i in xrange(9):
            if not self.isValidList([board[i][j] for j in xrange(9)]) or \
               not self.isValidList([board[j][i] for j in xrange(9)]):
                return False
        for i in xrange(3):
            for j in xrange(3):
                if not self.isValidList([board[m][n] for n in xrange(3 * j, 3 * j + 3) \
                                                     for m in xrange(3 * i, 3 * i + 3)]):
                    return False
        return True
    
    def isValidList(self, xs):
        xs = filter(lambda x: x != '.', xs)
        return len(set(xs)) == len(xs)

49. Group Anagrams

Given an array of strings, group anagrams together.
For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"],
Return:
[
["ate", "eat","tea"],
["nat","tan"],
["bat"]
]
Note: All inputs will be in lower-case.

实际上是一个字符串处理,不难。

class Solution(object):
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        res = []
        d = dict()
       
        for item in strs:
            flag = 1
            for key in d.keys():
                if self.isAnagrames(key,item):
                    d[key].append(item)
                    flag = 0
                    continue
            if flag:
                d[item] = [item]
        for item in d.values():
            res.append(item )
        return res
    
    def isAnagrames(self,key,item):
        if len(key) != len(item):
            return False
        hash_table = {}
        for i in key:
            if i not in hash_table:
                hash_table[i] = 1
            else:
                hash_table[i] += 1
        for c in item:
            if c not in hash_table:
                return False
            else:
                hash_table[c] -= 1
                if hash_table[c] == 0:
                    hash_table.pop(c)
        return hash_table == {}

上面关于判断两个字母是不是变位符字母的方法比较重要,利用hash表。但是处理时间超出限制,说明还不是最优。

class Solution(object):
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        anagrams_map, result = collections.defaultdict(list), []
        for s in strs:
            sorted_str = ("").join(sorted(s))
            anagrams_map[sorted_str].append(s)
        for anagram in anagrams_map.values():
            anagram.sort()
            result.append(anagram)
        return result

下面这种方法是一种常用的思路,先排序再比较,比较简洁。可是排序的复杂度比哈希更高啊,问题出在哪里。复杂度主要还是在于出现了两个for循环。

94. Binary Tree Inorder Traversal

Given a binary tree, return the inorder traversal of its nodes' values.
For example:
Given binary tree [1,null,2,3],
   1
    \
     2
    /
   3
return [1,3,2].

Note: Recursive solution is trivial, could you do it iteratively?
二叉树的中序遍历。有以下三种方式
前序遍历:根节点->左子树->右子树
中序遍历:左子树->根节点->右子树
后序遍历:左子树->右子树->根节点

有两种常用的解题思路,递归和非递归。第一步需要明白的是传入的参数到底是什么,按题意是一个数据结构。
第一种方法,用递归

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

class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        self.recursive(root,res)
        return res
        
    def recursive(self, root, res):
        if root:
            self.recursive(root.left, res)
            res.append(root.val)
            self.recursive(root.right, res)

if __name__ == '__main__':
    S = Solution()
    l1 = TreeNode(1)
    l2 = TreeNode(2)
    l3 = TreeNode(3)
    l4 = TreeNode(4)
    l5 = TreeNode(5)
    l6 = TreeNode(6)
    l7 = TreeNode(7)
    root = l1
    l1.left = l2
    l1.right = l3
    l2.left = l4
    l2.right = l5
    l3.left = l6
    l3.right = l7
    print S.inorderTraversal(root)

进一步理解函数之间参数传递的是引用。
第二种方法:入栈

class Solution2(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res, stack = [], []
        while root or stack:
            if root:
                stack.append(root)
                root = root.left
            else:
                root = stack.pop()
                res.append(root.val)
                root = root.right
        return res

上面这种方法运行效率似乎比递归低。两种方法都不难,主要还是解题思路,程序的每一步都很严谨。

136. Single Number

Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

找出一串数字中唯一出现一次的数字。这个题看起来比较简单,有不同的方法,首先想到的是哈希表,还有异或。

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = 0
        for item in nums:
            res = res ^ item
        return res

算是写过最简单的程序了。

138. Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.

带随意指针链表的深度拷贝,一开始抓不住问题的本质,考什么,随意指针意义何在。懂了,注意一点,指向随意位置,对源列表来说是有数据可以指向的,而拷贝过程中可能是没有的,而且位置不一样,拷贝列表的数据很简单,如何处理随意指针是个问题。
下面方法处理随意指针比较巧妙,分为三步:第一步复制节点不考虑random指针,并且是复制的节点紧接在原先节点的后面,并且合并。第二步处理random指针。第三步分离。
http://www.cnblogs.com/zuoyuan/p/3745126.html

class RandomListNode:
    def __init__(self, x):
        self.label = x
        self.next = None
        self.random = None

class Solution:
    # @param head, a RandomListNode
    # @return a RandomListNode
    def copyRandomList(self, head):
        # copy and combine copied list with original list
        current = head
        while current:
            copied = RandomListNode(current.label)
            copied.next = current.next
            current.next = copied
            current = copied.next
        
        # update random node in copied list
        current = head
        while current:
            if current.random:
                current.next.random = current.random.next
            current = current.next.next
        
        # split copied list from combined one
        dummy = RandomListNode(0)
        copied_current, current = dummy, head
        while current:
            copied_current.next = current.next
            current.next = current.next.next
            copied_current, current = copied_current.next, current.next
        return dummy.next

# Time:  O(n)
# Space: O(n)
class Solution2:
    # @param head, a RandomListNode
    # @return a RandomListNode
    def copyRandomList(self, head):
        dummy = RandomListNode(0)
        current, prev, copies = head, dummy, {}
        
        while current:
            copied = RandomListNode(current.label)
            copies[current] = copied
            prev.next = copied
            prev, current = prev.next, current.next
        
        current = head
        while current:
            if current.random:
                copies[current].random = copies[current.random]
            current = current.next
        
        return dummy.next

下面的程序找错。待完成

# not work till now
class Solution1(object):
    def copyRandomList(self, head):
        """
        :type head: RandomListNode
        :rtype: RandomListNode
        """
        mapdict = defaultdict(RandomListNode)
        if head is None:
            return None
        listcopy = RandomListNode(head.label)
        copyhead = listcopy
        while head:
            # for copy random
            if head in mapdict.keys():
                mapdict[head].random = listcopy
            mapdict[head.random] = listcopy
            # for copy label
            if head.next:
                next_item = RandomListNode(head.next.label)
                listcopy.next = next_item
                listcopy = listcopy.next

            head = head.next
        listcopy.next = None

        return copyhead

187. Repeated DNA Sequences

Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule
找到DNA序列中连续十个字符出现多次的子序列。
最简单的思路就是

class Solution(object):
   def findRepeatedDnaSequences(self, s):
       """
       :type s: str
       :rtype: List[str]
       """
       r, res = [],set()
       for i in xrange(len(s)):
           if len(s[i:]) < 10:
               break
           if s[i+1:].find(s[i:i+10]) != -1:
               res.add(s[i:i+10])
       
       for item in res:
           r.append(item)
       
       return r

注意有时可以使用一些梯子,不用都自己写。
但是明显复杂度比较高,超时了。
第二种思路根据网上多为编码,根据

class Solution2(object):
    def findRepeatedDnaSequences(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        res, tempset = set(), set()
        mapdict = {'A': 0, 'C': 1, 'G': 2, 'T': 3}
        encode = 0
        for i in xrange(len(s)):
            encode = (encode*4 + mapdict[s[i]]) & 0xFFFFF
            print encode
            if i < 9:
                continue
            if encode in tempset:
                res.add(s[i-9:i+1])
            else:
                tempset.add(encode)
        return list(res)

if __name__ == '__main__':
    s = Solution2()
    print s.findRepeatedDnaSequences("AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT")

值得注意的是 encode = (encode << 2 + mapdict[s[i]]) & 0xFFFFF,用移位操作符得出来的结果encode=0,不思其解。问题在于移位操作符运算优先级较低,需要'encode = ((encode << 2) + mapdict[s[i]]) & 0xFFFFF'
&的优先级也比较低,所以一般也可以不用加括号。

205. Isomorphic Strings

Given two strings s and t, determine if they are isomorphic.
Two strings are isomorphic if the characters in s can be replaced to get t.
All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.
For example,
Given "egg", "add", return true.
Given "foo", "bar", return false.
Given "paper", "title", return true.

判断两个字母是不是同构。

from collections import defaultdict

class Solution(object):
    def isIsomorphic(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        length = len(s)
        dic1, dic2 = defaultdict(list), defaultdict(list)
        for i in xrange(length):
            if s[i] in dic1:
                dic1[s[i]][1] += 1
            else:
                dic1[s[i]] = [i, 1]

            if t[i] in dic2:
                dic2[t[i]][1] += 1
            else:
                dic2[t[i]] = [i, 1]
            if dic2[t[i]] != dic1[s[i]]:
                return False
        return True
from itertools import izip  # Generator version of zip.

class Solution(object):
    def isIsomorphic(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if len(s) != len(t):
            return False

        s2t, t2s = {}, {}
        for p, w in izip(s, t):
            if w not in s2t and p not in t2s:
                s2t[w] = p
                t2s[p] = w 
            elif w not in s2t or s2t[w] != p:
                # Contradict mapping.
                return False
        return True

217. Contains Duplicate

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

看给定的数组有没有重复。
看起来不难,关键是如何降低复杂度。先尝试用字典。

class Solution(object):
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        s = set()
        for i in nums:
            if i in s:
                return True
            s.add(i)
        return False

class Solution2:
    # @param {integer[]} nums
    # @return {boolean}
    def containsDuplicate(self, nums):
        return len(nums) > len(set(nums))

219. Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.

这个题的意思是说给定一个列表,列表中重复的组合数不超过K个。
第一次题目意思理解错了。
https://www.hrwhisper.me/leetcode-contains-duplicate-i-ii-iii/
题意:给定一个数组和整数k,问数组中是否有i – j <=k 并且nums[i] == nums[j]的两个不同的下标 。

class Solution(object):
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        vis = {}
        for i, num in enumerate(nums):
            if num in vis and i - vis[num] <= k:
                return True
            vis[num] = i
        return False

242. Valid Anagram

Given two strings s and t, write a function to determine if t is an anagram of s.
For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.
Note:
You may assume the string contains only lowercase alphabets.
Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?

判断两个字符串,字母一样,只是位置不一样的。

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if len(s) != len(t):
            return False
        ls1, ls2 = [0 for _ in xrange(26)], [0 for _ in xrange(26)]
        for char in s:
            temp = ord(char) - ord('a')
            ls1[temp] += 1

        for char in t:
            temp = ord(char) - ord('a')
            ls2[temp] += 1

        for i in xrange(26):
            if ls1[i] != ls2[i]:
                return False
        return True

方法还可以优化,比如使用一个列表,第二个列表只需要递减操作就可以。其他思路:

class Solution:
    # @param {string} s
    # @param {string} t
    # @return {boolean}
    def isAnagram(self, s, t):
        if len(s) != len(t):
            return False

        count = {}

        for c in s:
            if c.lower() in count:
                count[c.lower()] += 1
            else:
                count[c.lower()] = 1

        for c in t:
            if c.lower() in count:
                count[c.lower()] -= 1
            else:
                count[c.lower()] = -1
            if count[c.lower()] < 0:
                return False

        return True
    
    def isAnagram2(self, s, t):
        return all([s.count(c)==t.count(c) for c in string.ascii_lowercase])
    
    def isAnagram3(self, s, t):
        if len(s) != len(t):
            return False 
        count = collections.defaultdict(int)
        for c in s:
            count[c] += 1
        for c in t:
            count[c] -= 1
            if count[c] < 0:
                return False
        return True

# Time:  O(nlogn)
# Space: O(n)
class Solution2:
    # @param {string} s
    # @param {string} t
    # @return {boolean}
    def isAnagram(self, s, t):
        return sorted(s) == sorted(t)

274. H-Index

A scientist has index h if h of his/her N papers have at least h citations each, and the other N − h papers have no more than h citations each

问题在于从一串数字中找到n个数都不小于n,并且其他的数都不大于n,这如何操作。
第一步是排序,从大到小排序,取其中n个数都大于n,确保n最大。

class Solution(object):
    def hIndex(self, citations):
        """
        :type citations: List[int]
        :rtype: int
        """
        length = len(citations)
        if length == 0:
            return 0

        citations = sorted(citations, reverse=True)
        print citations
        h = 0
        for i in xrange(0, length):
            if i == length-1:
                if citations[i] >= i+1:
                    h = i+1
            else:
                if citations[i] >= i+1 and citations[i+1] <= i+1:
                    h = i+1

        return h

测试通过,但是效率很低,只有6%。hint中提示用额外的空间,如何使用哈希表去优化。

    def hIndex2(self, citations):
        length = len(citations)
        if length == 0:
            return 0
        hash_table = [0 for _ in xrange(length+1)]
        for i in xrange(0, length):
            if citations[i] > length:
                hash_table[length] += 1
            else:
                hash_table[citations[i]] += 1

        paper = 0
        for i in xrange(length,-1,-1):
            paper += hash_table[i]
            if paper >= i:
                return i

避免了排序,使用哈希表,效率提升到40%。

class Solution2(object):
    def hIndex(self, citations):
        """
        :type citations: List[int]
        :rtype: int
        """
        citations.sort(reverse=True)
        h = 0
        for x in citations:
            if x >= h + 1:
                h += 1
            else:
                break
        return h
  
# Time:  O(nlogn)
# Space: O(n)
class Solution3(object):
    def hIndex(self, citations):
        """
        :type citations: List[int]
        :rtype: int
        """
        return sum(x >= i + 1 for i, x in enumerate(sorted(citations, reverse=True)))

290 word pattern

Given a pattern and a string str, find if str follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str.
Examples:
pattern = "abba", str = "dog cat cat dog" should return true.
pattern = "abba", str = "dog cat cat fish" should return false.
pattern = "aaaa", str = "dog cat cat dog" should return false.
pattern = "abba", str = "dog dog dog dog" should return false.

from itertools import izip

class Solution(object):
    def wordPattern(self, pattern, str):
        """
        :type pattern: str
        :type str: str
        :rtype: bool
        """
        words = str.split(' ')
        print words
        if len(pattern) != len(words):
            return False

        p2w, w2p = {}, {}
        for p, w in izip(pattern,words):
            if p not in p2w and w not in w2p:
                p2w[p] = w
                w2p[w] = p
            else:
                if w not in w2p or w2p[w] != p:
                    return False
        return True

思路比较重要。

299. Bulls and Cows

猜字游戏。

For example:
Secret number: "1807"
Friend's guess: "7810"
Hint: 1 bull and 3 cows. (The bull is 8, the cows are 0, 1 and 7.)
Write a function to return a hint according to the secret number and friend's guess, use A to indicate the bulls and B to indicate the cows. In the above example, your function should return "1A3B".

理解题意很关键:对输入,"1122","2211",输出是0A4B,"1123"
Friend's guess: "0111",输出是1A1B,注意的是第一个数字表示对应位置相同的个数,第二个表示位置不同但是和原始数字相同的字符个数。
还有一个比较重要的特征,不能一个循环得出结果,因为可能向后匹配。

from itertools import izip

class Solution(object):
    def getHint(self, secret, guess):
        """
        :type secret: str
        :type guess: str
        :rtype: str
        """
        bull, cows = 0, 0
        set1, set2 = set(), set()
        for s, g in izip(secret, guess):
            if s == g:
                bull += 1
            else:
                set1.add(s)
                set2.add(g)

        cows = len(set1 & set2)
        return '%dA%dB' % (bull, cows)

上面的方法最大的误区是使用了集合,导致‘2211’和‘1122’的输入结果出现偏差,因为集合中只包含不重复元素。

from itertools import izip
from collections import defaultdict

class Solution(object):
    def getHint(self, secret, guess):
        """
        :type secret: str
        :type guess: str
        :rtype: str
        """
        bull, cows = 0, 0
        d1, d2 = defaultdict(int), defaultdict(int)
        for s, g in izip(secret, guess):
            if s == g:
                bull += 1
            else:
                d1[s] += 1
                d2[g] += 1

        for key in d1.keys():
            cows += min(d1[key], d2[key])
        return '%dA%dB' % (bull, cows)

参考:

from collections import Counter
from itertools import imap

class Solution2(object):
    def getHint(self, secret, guess):
        """
        :type secret: str
        :type guess: str
        :rtype: str
        """
        A = sum(imap(operator.eq, secret, guess))
        B = sum((Counter(secret) & Counter(guess)).values()) - A
        return "%dA%dB" % (A, B)

336、palindrome pairs

给定一组唯一的单词。从中寻找所有的下标对(i, j),使得对应下标的单词拼接,亦即:words[i] + words[j]是回文

class Solution(object):
    def palindromePairs(self, words):
        """
        :type words: List[str]
        :rtype: List[List[int]]
        """
        res =[]
        for i, word1 in enumerate(words):
            for j, word2 in enumerate(words[i+1:], i+1):
                if self.isPalindrome(word1+word2):
                    res.append([i,j])
                if self.isPalindrome(word2+word1):
                    res.append([j,i])
        return res


    def isPalindrome(self,word):
        length = len(word)
        begin, end = 0,length-1
        while begin < end:
            if word[begin] != word[end]:
                return False
            begin += 1
            end -= 1
        return True
if __name__ == '__main__':
    s = Solution()
    print s.palindromePairs(["abcd", "dcba", "lls", "s", "sssll"])

可以预见上面的解法效率不是很高,根据提示,这道题适合tire树求解。

class TrieNode:
    def __init__(self):
        self.word_idx = -1
        self.leaves = {}

    def insert(self, word, i):
        cur = self
        for c in word:
            if not c in cur.leaves:
                cur.leaves[c] = TrieNode()
            cur = cur.leaves[c]
        cur.word_idx = i

    def find(self, s, idx, res):
        cur = self
        for i in reversed(xrange(len(s))):
            if s[i] in cur.leaves:
                cur = cur.leaves[s[i]]
                if cur.word_idx not in (-1, idx) and \
                   self.is_palindrome(s, i - 1):
                    res.append([cur.word_idx, idx])
            else:
                break

    def is_palindrome(self, s, j):
        i = 0
        while i <= j:
            if s[i] != s[j]:
                return False
            i += 1
            j -= 1
        return True

class Solution_MLE(object):
    def palindromePairs(self, words):
        """
        :type words: List[str]
        :rtype: List[List[int]]
        """
        res = []
        trie = TrieNode()
        for i in xrange(len(words)):
            trie.insert(words[i], i)

        for i in xrange(len(words)):
            trie.find(words[i], i, res)

        return res

下面程序运行正常:

class Solution(object):
    def palindromePairs(self, words):
        """
        :type words: List[str]
        :rtype: List[List[int]]
        """
        res = [] 
        lookup = {}
        for i, word in enumerate(words):
            lookup[word] = i

        for i in xrange(len(words)):
            for j in xrange(len(words[i]) + 1):
                prefix = words[i][j:]
                suffix = words[i][:j]
                if prefix == prefix[::-1] and \
                   suffix[::-1] in lookup and lookup[suffix[::-1]] != i:
                    res.append([i, lookup[suffix[::-1]]])
                if j > 0 and suffix == suffix[::-1] and \
                   prefix[::-1] in lookup and lookup[prefix[::-1]] != i:
                    res.append([lookup[prefix[::-1]], i])
        return res

347、top k frequent elements

Given a non-empty array of integers, return the k most frequent elements.
For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].
Note:
You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

from collections import defaultdict
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        lookup = defaultdict(int)
        for item in nums:
            lookup[item] += 1

        sorted_lookup = sorted(lookup.items(), key=lambda item:item[1], reverse=True)
        return [item[0] for item in sorted_lookup[0:k]]

下面方法号称桶排序,但是效率并没有提升。

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        counts = collections.Counter(nums)
        buckets = [[] for _ in xrange(len(nums)+1)]
        for i, count in counts.iteritems():
            buckets[count].append(i)
            
        result = []
        for i in reversed(xrange(len(buckets))):
            for j in xrange(len(buckets[i])):
                result.append(buckets[i][j])
                if len(result) == k:
                    return result
        return result

用python库函数Counter

from collections import Counter

class Solution(object):
    def topKFrequent(self,nums,k):
        c = Counter(nums)
        temp = c.most_common(k)
        return [item[0] for item in temp]

350. Intersection of Two Arrays II

求两个列表的交集,比较简单。

from collections import defaultdict

class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        res = []
        dict1 = defaultdict(int)
        for item in nums1:
            dict1[item] += 1
        for item in nums2:
            if item in dict1:
                res.append(item)
                dict1[item] -= 1
                if dict1[item] == 0:
                    del dict1[item]
        return res

355、design twitter

Twitter twitter = new Twitter();

// User 1 posts a new tweet (id = 5).
twitter.postTweet(1, 5);

// User 1's news feed should return a list with 1 tweet id -> [5].
twitter.getNewsFeed(1);

// User 1 follows user 2.
twitter.follow(1, 2);

// User 2 posts a new tweet (id = 6).
twitter.postTweet(2, 6);

// User 1's news feed should return a list with 2 tweet ids -> [6, 5].
// Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5.
twitter.getNewsFeed(1);

// User 1 unfollows user 2.
twitter.unfollow(1, 2);

// User 1's news feed should return a list with 1 tweet id -> [5],
// since user 1 is no longer following user 2.
twitter.getNewsFeed(1);

设计twitter的一些简单功能,包括发布,更新,订阅和取消订阅,完成相关API的设计。

from collections import defaultdict
class Twitter(object):
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.post_twitter = defaultdict(list)   # userId -> tweetId
        self.follow_map = defaultdict(set)     # userId -> followee
        self.time = 0



    def postTweet(self, userId, tweetId):
        """
        Compose a new tweet.
        :type userId: int
        :type tweetId: int
        :rtype: void
        """
        self.time += 1
        self.post_twitter[userId].append((self.time, tweetId))

    def getNewsFeed(self, userId):
        """
        Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.
        :type userId: int
        :rtype: List[int]
        """
        allmessage = []
        allmessage.extend(self.post_twitter[userId])
        for user in self.follow_map[userId]:
            allmessage.extend(self.post_twitter[user])
        smessage = sorted(allmessage, key=lambda item: item[0], reverse=True)[0:10]
        return [item[1] for item in smessage]       



    def follow(self, followerId, followeeId):
        """
        Follower follows a followee. If the operation is invalid, it should be a no-op.
        :type followerId: int
        :type followeeId: int
        :rtype: void
        """
        if followeeId != followerId:
            self.follow_map[followerId].add(followeeId)

    def unfollow(self, followerId, followeeId):
        """
        Follower unfollows a followee. If the operation is invalid, it should be a no-op.
        :type followerId: int
        :type followeeId: int
        :rtype: void
        """
        if followeeId != followerId:
            self.follow_map[followerId].discard(followeeId)

其中值得注意的是,取最新的1十个状态,可以用堆排序,效率会提高。

你可能感兴趣的:(hash_table-special)