目錄:
- 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
下面這種方法是一種常用的思路,先排序再比較,比較簡潔??墒桥判虻膹碗s度比哈希更高啊,問題出在哪里。復雜度主要還是在于出現了兩個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十個狀態,可以用堆排序,效率會提高。