Like San Mateo


Table of Content

Table of Content  

637. Average of Levels in Binary Tree    7

597. Friend Requests I: Overall Acceptance Rate    8

157. Read N Characters Given Read4    8

398. Random Pick Index    8

314. Binary Tree Vertical Order Traversal    9

209. Minimum Size Subarray Sum    10

283. Move Zeroes    11

311. Sparse Matrix Multiplication    11

17. Letter Combinations of a Phone Number    11

91. Decode Ways    12

56. Merge Intervals    12

49. Group Anagrams    13

43. Multiply Strings    14

128. Longest Consecutive Sequence    14

297. Serialize and Deserialize Binary Tree    15

23. Merge k Sorted Lists    16

325. Maximum Size Subarray Sum Equals k    17

252. Meeting Rooms    17

253. Meeting Rooms II    18

277. Find the Celebrity    18

161. One Edit Distance    19

377. Combination Sum IV    20

211. Add and Search Word - Data structure design    21

477. Total Hamming Distance    23

286. Walls and Gates    23

146. LRU Cache    23

285. Inorder Successor in BST    25

261. Graph Valid Tree    25

274. H-Index    27

117. Populating Next Right Pointers in Each Node II    27

275. H-Index II    28

208. Implement Trie (Prefix Tree)    28

554. Brick Wall    30

525. Contiguous Array    31

523. Continuous Subarray Sum    32

621. Task Scheduler    33

210. Course Schedule II    34

636. Exclusive Time of Functions    35

653. Two Sum IV - Input is a BST    36

15. 3Sum    36

121. Best Time to Buy and Sell Stock    37

75. Sort Colors    38

78. Subsets    38

79. Word Search    39

238. Product of Array Except Self    40

33. Search in Rotated Sorted Array    40

90. Subsets II    41

380. Insert Delete GetRandom O(1)    41

88. Merge Sorted Array    43

26. Remove Duplicates from Sorted Array    43

80. Remove Duplicates from Sorted Array II    44

69. Sqrt(x)    45

168. Excel Sheet Column Title    45

173. Binary Search Tree Iterator    45

572. Subtree of Another Tree    46

543. Diameter of Binary Tree    47

404. Sum of Left Leaves    47

200. Number of Islands    48

133. Clone Graph    49

278. First Bad Version    49

461. Hamming Distance    50

477. Total Hamming Distance    50

67. Add Binary    50

125. Valid Palindrome    51

49. Group Anagrams    52

25. Reverse Nodes in k-Group    52

301. Remove Invalid Parentheses    53

76. Minimum Window Substring    55

79. Word Search    55

Replace %20    56

62. Unique Paths    56

63. Unique Paths II    57

367. Valid Perfect Square    58

98. Validate Binary Search Tree    58

234. Palindrome Linked List    59

637. Average of Levels in Binary Tree

思路: BFS, 每層算 average
#         self.right = None

class Solution(object):
   def averageOfLevels(self, root):
       """
       :type root: TreeNode
       :rtype: List[float]
       """
       q, res, path = [], [], []
       q.append(root)
       while q:
           for i in range(len(q)):
               temp = q[0]
               del q[0]
               path.append(temp.val)
               if temp.left:  q.append(temp.left)
               if temp.right: q.append(temp.right)
           res.append(sum(path)/(len(path)/1.0))
           path = []
       return res

597. Friend Requests I: Overall Acceptance Rate

思路: SQL 題
SELECT case when res.num_requests = 0 then 0.00 else ROUND(res.num_accepted*1.0/res.num_requests,2) end as accept_rate
FROM
(SELECT COUNT(DISTINCT f.sender_id, f.send_to_id) as num_requests, COUNT(DISTINCT r.requester_id, r.accepter_id) as num_accepted
FROM friend_request f, request_accepted r) res

157. Read N Characters Given Read4

# The read4 API is already defined for you.
# @param buf, a list of characters
# @return an integer
# def read4(buf):

class Solution(object):
   def read(self, buf, n):
       """
       :type buf: Destination buffer (List[str])
       :type n: Maximum number of characters to read (int)
       :rtype: The number of characters read (int)
       """
       read_bytes, buffers = 0 , [''] * 4
       for i in range(n/4 + 1):
           size = read4(buffers)
           if size:
               buf[read_bytes : read_bytes + size] = buffers
               read_bytes += size
           else:
               break
       return min(n, read_bytes)

398. Random Pick Index

思路: 設計題, 記得用 random.randint()
class Solution(object):

   def __init__(self, nums):
       """
       
       :type nums: List[int]
       :type numsSize: int
       """
       self.nums = nums
       self.numsSize = len(nums)
       self.r = []

       
   def pick(self, target):
       """
       :type target: int
       :rtype: int
       """
       for i in xrange(self.numsSize):
           if self.nums[i] == target:
               self.r.append(i)
       
       x = self.r[random.randint(0,len(self.r)-1)]
       self.r = []
       return x

314. Binary Tree Vertical Order Traversal

思路: BFS 遞迴, 新增一個 index 每次往左加子數 就減 1 往右則加 1
最後根據 index 加到 res

# 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 verticalOrder(self, root):
       """
       :type root: TreeNode
       :rtype: List[List[int]]
       """
       if not root: return []
       
       q, path, res, col = [], {}, [], 0
       col_min, col_max = 0, 0
       q.append([root,col])
       while q:
           for i in range(len(q)):
               # pop left
               temp = q[0]
               del q[0]
               # have the flag to remember the left / right bound
               if temp[1] > col_max: col_max = temp[1]
               if temp[1] < col_min: col_min = temp[1]
               # save val base on column level
               if temp[1] not in path:
                   path[temp[1]] = [temp[0].val]
               else:
                   path[temp[1]].append(temp[0].val)
               # add child node into queue
               if temp[0].left:  q.append( [temp[0].left,  temp[1]-1] )
               if temp[0].right: q.append( [temp[0].right, temp[1]+1] )
       # format the result
       for j in range( col_min, col_max+1 ):
           res.append( path[j] )
       return res

Second try:
   def verticalOrder(self, root):
       """
       :type root: TreeNode
       :rtype: List[List[int]]
       """
       m = {}
       res = []
       q = []
       q.append((root, 0))
       while q:
           temp = q[0]
           del q[0]
           if temp[1] not in m:
               m[temp[1]] = [temp[0].val]
           else:
               m[temp[1]].append(temp[0].val)
           if temp.left:  q.append(temp[0].left,  temp[1]-1)
           if temp.right: q.append(temp[0].right, temp[1]+1)
       
       l, r = 0, 0
       while l in m:
           l -= 1
       l += 1
       while r in m:
           r += 1
       r -= 1
       
       for i in range(l,r+1):
           res.append(m[i])
       return res

209. Minimum Size Subarray Sum

思路: 最短子數組和, 要求兩種寫法 O(N), O(n log n)
O(n) : 雙指針
O(n log n) : 二分搜索
值得特別注意的是 題目要求的是 大於等於 target 這裡就是 s. 而不是僅僅等於 target就好

class Solution(object):
   def minSubArrayLen(self, s, nums):
       """
       :type s: int
       :type nums: List[int]
       :rtype: int
       """
       size = len(nums)
       start, end, ans, tot = 0, 0, size + 1, 0
       while True:
           if tot < s:
               if end == size: break
               tot += nums[end]
               end += 1
           else:
               if start > end: break
               ans = min((end - start), ans)
               tot -= nums[start]
               start += 1
       return ans if ans <= size else 0

283. Move Zeroes

思路: 經典題, 雙指針 一定要多練習

class Solution(object):
   def moveZeroes(self, nums):
       """
       :type nums: List[int]
       :rtype: void Do not return anything, modify nums in-place instead.
       """
       y = 0
       for i in range(len(nums)):
           if nums[i]:
               nums[i], nums[y] = nums[y], nums[i]
               y += 1

Second Try: 用count 和 deep copy

       numberOfZero = nums.count(0)
       nonZero = [x for x in nums if x != 0]
       nums[:] = nonZero + [0] * numberOfZero

311. Sparse Matrix Multiplication

class Solution(object):
   def multiply(self, A, B):
       mA,nA,nB = len(A),len(A[0]),len(B[0])
       res = [[0]*len(B[0]) for _ in xrange(mA)]
       for i in xrange(mA):
           for j in xrange(nA):
               if A[i][j]:
                   for k in xrange(nB):
                       res[i][k] += A[i][j]*B[j][k]
       return res
我们知道一个 i x k 的矩阵A乘以一个 k x j 的矩阵B会得到一个 i x j 大小的矩阵C,那么我们来看结果矩阵中的某个元素C[i][j]是怎么来的,起始是A[i][0]*B[0][j] + A[i][1]*B[1][j] + ... + A[i][k]*B[k][j]

17. Letter Combinations of a Phone Number

思路: DFS, 對每個數字代表的字母 DFS

class Solution(object):
   def letterCombinations(self, digits):
       def dfs(index, path):
           if index == size:
               res.append(path)
               Return
#防止input 不 [2-9]
           if digits[index] not in dict:
               dfs(index+1, path+'*')
           else:
               for i in dict[digits[index]]:
                   dfs(index+1, path+i)

       dict = {'2': ['a','b','c'],'3': ['d','e','f'],'4': ['g','h','i'],
              '5': ['j','k','l'],'6': ['m','n','o'],'7': ['p','q','r','s'],
               '8': ['t','u','v'],'9': ['w','x','y','z']
              }
       res, size = [], len(digits)
       if not size: return res
       dfs(0, '')
       return res

91. Decode Ways

思路: 求有幾種方法的題目, 通常用DP
这道题要求解码方法,跟之前那道 Climbing Stairs 爬梯子问题 非常的相似,但是还有一些其他的限制条件,比如说一位数时不能为0,两位数不能大于26,其十位上的数也不能为0,出去这些限制条件,根爬梯子基本没啥区别,也勉强算特殊的斐波那契数列,当然需要用动态规划Dynamci Programming来解。建立一位dp数组,长度比输入数组长多多2,全部初始化为1,因为斐波那契数列的前两项也为1,然后从第三个数开始更新,对应数组的第一个数。对每个数组首先判断其是否为0,若是将改为dp赋0,若不是,赋上一个dp值,此时相当如加上了dp[i - 1], 然后看数组前一位是否存在,如果存在且满足前一位不是0,且和当前为一起组成的两位数不大于26,则当前dp值加上dp[i - 2], 至此可以看出来跟斐波那契数组的递推式一样


class Solution(object):
   def numDecodings(self, s):
       """
       :type s: str
       :rtype: int
       """
       if s=="" or s[0]=='0': return 0
       dp=[1,1]
       for i in range(2,len(s)+1):
           if 10 <=int(s[i-2:i]) <=26 and s[i-1]!='0':
               dp.append(dp[i-1]+dp[i-2])
           elif int(s[i-2:i])==10 or int(s[i-2:i])==20:
               dp.append(dp[i-2])
           elif s[i-1]!='0':
               dp.append(dp[i-1])
           else:
               return 0
       return dp[len(s)]

Second Try:
class Solution(object):
   def numDecodings(self, s):
       if not s: return 0
       dp = [0] * (len(s) + 1)
       dp[0] = 1
       for i in range(1,len(s)+1):
           if s[i-1] != '0':
               dp[i] = dp[i-1]
           if i > 1 and  10 <= int(s[i-2:i]) <= 26:
               dp[i] += dp[i-2]
           print dp
       return dp[-1]
       

56. Merge Intervals

思路:  區間合併, 這題跟 meeting room II 很像 就是檢查當前的interval 可不可以和別人合併
我們可以先排序 這樣就只要掃一遍 intervals, 邊掃邊合併就ok!

For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].

# Definition for an interval.
# class Interval(object):
#     def __init__(self, s=0, e=0):
#         self.start = s
#         self.end = e

class Solution(object):
   def merge(self, intervals):
       """
       :type intervals: List[Interval]
       :rtype: List[Interval]
       """
       intervals = sorted(intervals, key=lambda x: x.start)
       result = []
       for interval in intervals:
           if len(result) == 0 or result[-1].end < interval.start:
               result.append(interval)
           else:
               result[-1].end = max(result[-1].end, interval.end)
       return result
二刷:
class Solution(object):
   def merge(self, intervals):
       """
       :type intervals: List[Interval]
       :rtype: List[Interval]
       """
       res = []
       intervals = sorted(intervals, key=lambda x: x.start)
       for i in range(len(intervals)):
           # Do merge
           if len(res) == 0 or res[-1].end < intervals[i].start:
               temp = Interval()
               temp.start = intervals[i].start
               temp.end =   intervals[i].end
               res.append(temp)
           else:
               res[-1].end = max(res[-1].end, intervals[i].end)
       return res

三刷:
       res = []
       intervals = sorted(intervals, key = lambda x: x.start)
       for i in range(len(intervals)):
           if len(res) == 0 or res[-1].end < intervals[i].start:
               res.append(intervals[i])
           else:
               res[-1].end = max(res[-1].end, intervals[i].end)
       return res

49. Group Anagrams

思路: 錯位詞, 指的是 長度一樣但是 element 位置不同 比方說 abc和cba
掃一遍題目給的 list 對 每個詞排序 之後丟進字典

class Solution(object):
   def groupAnagrams(self, strs):
       """
       :type strs: List[str]
       :rtype: List[List[str]]
       """
       res, dic = [], {}
       for i in strs:
           temp = "".join(sorted(list(i)))
           if temp in dic:
               dic[temp].append(i)
           else:
               dic[temp] = [i]
       for j in dic:
           res.append(dic[j])
           
       return res

43. Multiply Strings

思路: 大數相乘, 分三個步驟
  1. 數字兩兩相乘 像 直式乘法
  2. 計算進位
  3. 去掉所有開頭的 0

class Solution(object):
   def multiply(self, num1, num2):
       """
       :type num1: str
       :type num2: str
       :rtype: str
       """
       size_1 = len(num1)
       size_2 = len(num2)
       size_total = size_1 + size_2
       res = [ 0 for _ in range(size_total) ]
       num1, num2 = num1[::-1], num2[::-1]
       for i in range(size_1):
           for j in range(size_2):
               res[ i+j ] += int(num1[i]) * int(num2[j])
       
       for k in range(len(res)):
           if k < len(res)-1:
               res[k+1] += res[k] / 10
               res[k] %= 10
               res[k] = str(res[k])
       for _ in range(len(res)):
           res[_] = str(res[_])
       res = res[::-1]
       
       while res:
           if res[0] == '0':
               del res[0]
           else:
               break
       
       
       return ''.join(res) if len(res) >= 1 else '0'

128. Longest Consecutive Sequence

思路: 雙指針包夾的window, 找出最長的window size. 這裡因為題目是問 連續的序列所以我們找window的時候是對 nums的值一個一個做搜索 往上跟往下找出window的大小 一旦找到了上界 則 flag = 1 同樣的找到了下界 flag2 = 1

class Solution(object):
   def longestConsecutive(self, nums):
       """
       :type nums: List[int]
       :rtype: int
       """
       res = 0
       dict = collections.Counter(nums)
       # corner case
       if len(nums) <= 1: return len(nums)
       
       # algr
       for i in range(len(nums)):
           start = 0
           end = 0
           j = 1
           flag, flag2 = 0, 0
           
           while True:
               if flag == 0 and nums[i]+j in dict: end += 1
               else: flag += 1
               if flag2 == 0 and nums[i]-j in dict: start -= 1
               else: flag2 += 1
               if flag > 0 and flag2 > 0:
                   break
               j += 1
           
           res = max((end-start)+1, res)
           # bracktrack, if we already found the best case
           if res == len(nums): return res
       return res

297. Serialize and Deserialize Binary Tree

思路: 對BST 拆分 再組合回來. 都用 DFS 進行前序遍歷, 組合回來的時候用,
           node = TreeNode(int(val))
           node.left = dfs()
           node.right = dfs()

class Codec:

   def serialize(self, root):
       """Encodes a tree to a single string.
       
       :type root: TreeNode
       :rtype: str
       """
       def dfs(node):
           if not node: return
           res.append(str(node.val))
           if node.left: dfs(node.left)
           else: res.append('null')
           if node.right: dfs(node.right)
           else: res.append('null')
       
       res = []
       dfs(root)
       return res

   def deserialize(self, data):
       """Decodes your encoded data to tree.
       
       :type data: str
       :rtype: TreeNode
       """
       def dfs():
           val = vals.next()
           if val == 'null': return
           node = TreeNode(int(val))
           node.left = dfs()
           node.right = dfs()
           return node
       
       if not data: return []
       vals = iter(data)
       return dfs()

23. Merge k Sorted Lists

思路: 先寫一個 merge two list 的 function. 之後對 k 倆倆合併

class Solution(object):
   def mergeKLists(self, lists):
       """
       :type lists: List[ListNode]
       :rtype: ListNode
       """
       def mergeTwoLists(l1, l2):
               """
               :type l1: ListNode
               :type l2: ListNode
               :rtype: ListNode
               """
               if not l1 and not l2: return
               if l1 and not l2: return l1
               if l2 and not l1: return l2

               dummy = ListNode(0)
               curr = dummy
               while l1 and l2:
                   if l1.val <= l2.val:
                       dummy.next = l1
                       dummy = dummy.next
                       l1 = l1.next
                   else:
                       dummy.next = l2
                       dummy = dummy.next
                       l2 = l2.next
               if l1: dummy.next = l1
               if l2: dummy.next = l2

               return curr.next
       while lists:
           if len(lists) <= 1:
               return lists[0]
           else:
               temp = mergeTwoLists(lists[0], lists[1])
               lists[1] = temp
               del lists[0]

325. Maximum Size Subarray Sum Equals k

思路: 使用字典数据结构,然后累加之后对index进行比较。
Tip:累加为0需要先填写,否则中间段出现的0的话,就会值计算从中间段开始的index,而出现0的话应该从头计算,因为之前的所有加起来刚好是0,需要补充到最大的subarray里。


class Solution(object):
   def maxSubArrayLen(self, nums, k):
       """
       :type nums: List[int]
       :type k: int
       :rtype: int
       """
       res , acc = 0, 0
       dic = {0: -1}
       
       for i in range(len(nums)):
           acc += nums[i]
           if acc not in dic:
               dic[acc] = i
           if acc - k in dic:
               res = max(res, i - dic[acc-k])
       return res

252. Meeting Rooms

思路: 對room的schedule 做個排序
假設 schedule [1,3] 給request [2,4] 則 返回 False. 所以我們要判斷schedule.end < request.start 則返回 False

# Definition for an interval.
# class Interval(object):
#     def __init__(self, s=0, e=0):
#         self.start = s
#         self.end = e

class Solution(object):
   def canAttendMeetings(self, intervals):
       """
       :type intervals: List[Interval]
       :rtype: bool
       """
       intervals = sorted(intervals, key = lambda intervals : intervals.start)
       if len(intervals) <= 1: return True
       
       for i in range( 1,len(intervals) ):
           before = intervals[i-1].end
           end    = intervals[i].start
           if end < before :
               return False
       return True

253. Meeting Rooms II

思路:
掃所有房間的 schedule
關鍵在如果 meeting.start >= root. end 則不用增加新房間 只要把 room.end 延伸至 meeting.start
否則新增

# Definition for an interval.
# class Interval(object):
#     def __init__(self, s=0, e=0):
#         self.start = s
#         self.end = e

class Solution(object):
   def minMeetingRooms(self, intervals):
       """
       :type intervals: List[Interval]
       :rtype: int
       """
       room = 0
       meetings = []
       for i in sorted(intervals, key = lambda intervals : intervals.start):
           found = False
           for meeting in meetings:
               # continue push end boundary
               if i.start >= meeting.end:
                   meeting.end = i.end
                   found = True
                   break
           if not found:
               meetings.append(i)
               room += 1
       return room

277. Find the Celebrity

# The knows API is already defined for you.
# @param a, person a
# @param b, person b
# @return a boolean, whether a knows b
# def knows(a, b):

思路:
兩個邏輯:
如果 a 知道 b 則 a 不是名人
如果 a 不知道 b 則 b 不是名人
題目說只有0個或1個名人在 party 我們先掃一遍pool 如果a 知道b 則a 自己本身一定不是名人 candidate = b
之後分成前後兩半 做判斷~

# The knows API is already defined for you.
# @param a, person a
# @param b, person b
# @return a boolean, whether a knows b
# def knows(a, b):

class Solution(object):
   def findCelebrity(self, n):
       """
       :type n: int
       :rtype: int
       """
       res = 0
       for i in xrange(n):
           if knows(res, i): res = i
       for i in xrange(res):
           if knows(res, i) or not knows(i, res): return -1
       for i in xrange(res + 1, n):
           if knows(res, i) or not knows(i, res): return -1
       return res


思路:
兩個邏輯:
如果 a 知道 b 則 a 不是名人
如果 a 不知道 b 則 b 不是名人
題目說只有0個或1個名人在 party 我們先掃一遍pool 如果a 知道b 則a 自己本身一定不是名人 candidate = b
分成兩半可以合併 成一個 for loop 用 if res == i 判斷並跳過
時間複雜度 O(n)
空間複雜度  O(1)

class Solution(object):
   def findCelebrity(self, n):
       """
       :type n: int
       :rtype: int
       """
       res = 0
       for i in range(n):
           if knows(res, i): res = i
       for i in range(n):
           if i == res: continue
           if knows(res, i) or not knows(i, res): return -1
       
       return res


161. One Edit Distance

思路: 掃一遍字串 如果兩字串的某個element 不相等 則分為三種情況
  1. 字串s 比 字串 t 長
  2. 兩字串等長
  3. 字串s  比字串t 短
分別比較 element 之後的字串是否相等, 如果都沒有某個element 不相等
則最後檢查一下 兩字串長是否相差 1

import collections
class Solution(object):
   def isOneEditDistance(self, s, t):
       """
       :type s: str
       :type t: str
       :rtype: bool
       """
       sl = len(s)
       tl = len(t)
       flag = 0
       if abs(sl - tl) > 1 : return False
       for i in range(min(sl, tl)):
           if s[i] != t[i]:
               if sl > tl:    return s[i+1:] == t[i:]
               elif sl == tl: return s[i+1:] == t[i+1:]
               else:  return s[i:] == t[i+1:]
       return abs(sl - tl) == 1
               

377. Combination Sum IV

思路: 傳統dfs 遞迴花的時間太久, 用DP 來做   if i + x <= target: dp[i + x] += dp[i]

DP:
class Solution(object):
   def combinationSum4(self, nums, target):
       """
       :type nums: List[int]
       :type target: int
       :rtype: int
       """
       dp = [1] + [0] * target
       for i in xrange(target + 1):
           for x in nums:
               if i + x <= target:
                   dp[i + x] += dp[i]
       return dp[target]


DFS: LTE

class Solution(object):
   def combinationSum4(self, nums, target):
       """
       :type nums: List[int]
       :type target: int
       :rtype: int
       """
       nl = len(nums)
       if nl == 0: return 0
       res = []
       
       def dfs(node, path):
           path.append(node)
           if sum(path) > target: return
           elif sum(path) == target:
               if path not in res:
                   res.append(path)
           else:
               for j in range(nl):
                   dfs(nums[j], path[:])
       
       for i in range(nl):
           dfs(nums[i], [])
       return len(res)

211. Add and Search Word - Data structure design

思路: 設計題, 在 add的時候 設計 pool 為一個字典 增加搜索速度

class WordDictionary(object):

   def __init__(self):
       """
       Initialize your data structure here.
       """
       self.pool = {}

   def addWord(self, word):
       """
       Adds a word into the data structure.
       :type word: str
       :rtype: void
       """
       if len(word) not in self.pool:
           self.pool[len(word)] = [word]
       if word not in self.pool[len(word)]:
           self.pool[len(word)].append(word)
   
   def search(self, word):
       """
       Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
       :type word: str
       :rtype: bool
       """
       Ndot = []
       wl = len(word)
       for i in range(len(word)):
           if word[i] != '.':
               Ndot.append(i)
       if wl in self.pool:
           for j in self.pool[wl]:
               flag = 0
               if len(j) == len(word):
                   for k in Ndot:
                       if word[k] != j[k]:
                           flag = 1
                           break
                   if flag == 0 : return True
       return False
               


# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)

Second Try:
複雜度 O(n^2)

class WordDictionary(object):

   def __init__(self):
       """
       Initialize your data structure here.
       """
       self.pool = {}

   def addWord(self, word):
       """
       Adds a word into the data structure.
       :type word: str
       :rtype: void
       """
       if len(word) not in self.pool:
           self.pool[len(word)] = [word]
       elif word not in self.pool[len(word)]:
           self.pool[len(word)].append(word)
   
   def search(self, word):
       """
       Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
       :type word: str
       :rtype: bool
       """
       if len(word) in self.pool:
           if word in self.pool[len(word)]:
               #print "h1"
               return True
           else:
               for i in range(len(self.pool[len(word)])):
                   for j in range(len(word)):
                       if word[j] == '.' or word[j] == self.pool[len(word)][i][j]:
                           if j == len(word)-1:
                               return True
                           continue
                       else:
                           break
       return False

477. Total Hamming Distance

思路: 計算所有 0 和 1 的個數 然後相乘

class Solution(object):
   def totalHammingDistance(self, nums):
       """
       :type nums: List[int]
       :rtype: int
       """
       ans = 0
       for x in range(32):
           mask = 1 << x
           zero = one = 0
           for num in nums:
               if num & mask:
                   one += 1
               else:
                   zero += 1
           ans += zero * one
       return ans

286. Walls and Gates

思路: 大神的解答, 先找出0 也就是門的位置 然後對門的四周做BFS 超出矩陣就不算
每到一格矩陣內的值 加一 並把他丟進 queue

class Solution(object):
   def wallsAndGates(self, rooms):
       """
       :type rooms: List[List[int]]
       :rtype: void Do not return anything, modify rooms in-place instead.
       """
       q = [(i, j) for i, row in enumerate(rooms) for j, r in enumerate(row) if not r]
       for i, j in q:
           for I, J in (i+1, j), (i-1, j), (i, j+1), (i, j-1):
               if 0 <= I < len(rooms) and 0 <= J < len(rooms[0]) and rooms[I][J] > 2**30:
                   rooms[I][J] = rooms[i][j] + 1
                   q += (I, J),

146. LRU Cache

思路: 這裡用orderedDict 做 會很直觀
Get: 相對簡單的 function. 如果值存在 就把這值拉到最新更新 沒有就返回 -1
Put: 如果值存在 拉出來並且更新放回去 或者 catch 值已滿 就先丟掉最少用的 在放新值 進去


另一種做法是 dict + double link list

class LRUCache(object):

   def __init__(self, capacity):
       """
       :type capacity: int
       """
       self.capacity = capacity
       self.cache = collections.OrderedDict()
       
   def get(self, key):
       """
       :type key: int
       :rtype: int
       """
       if not key in self.cache:
           return -1
       value = self.cache.pop(key)
       self.cache[key] = value
       return value

   def put(self, key, value):
       """
       :type key: int
       :type value: int
       :rtype: void
       """
       if key in self.cache:
           self.cache.pop(key)
       elif len(self.cache) == self.capacity:
           self.cache.popitem(last=False)
       self.cache[key] = value

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

Second try:
class LRUCache(object):

   def __init__(self, capacity):
       """
       :type capacity: int
       """
       self.capacity = capacity
       self.cache = collections.OrderedDict()


   def get(self, key):
       """
       :type key: int
       :rtype: int
       """
       if key not in self.cache:
           return -1
       else:
           self.cache[key] = self.cache.pop(key)
           return self.cache[key]

   def put(self, key, value):
       """
       :type key: int
       :type value: int
       :rtype: void
       """
       if key in self.cache:
           self.cache.pop(key)
       elif len(self.cache) == self.capacity:
           self.cache.popitem(last=False)
       self.cache[key] = value

285. Inorder Successor in BST

思路:
这种方法充分地利用到了BST的性质,我们首先看根节点值和p节点值的大小,如果根节点值大,说明p节点肯定在左子树中,那么此时我们先将res赋为root,然后root移到其左子节点,循环的条件是root存在,我们再比较此时root值和p节点值的大小,如果还是root值大,我们重复上面的操作,如果p节点值,那么我们将root移到其右子节点,这样当root为空时,res指向的就是p的后继节点


# 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 inorderSuccessor(self, root, p):
       """
       :type root: TreeNode
       :type p: TreeNode
       :rtype: TreeNode
       """
       res = None
       while root:
           if root.val > p.val:
               res = root.val
               root = root.left
           else:
               root = root.right

       return res


261. Graph Valid Tree

思路: 題目問給的edges可不可以畫出一棵樹, 樹的本值是連通並且無環.

構造圖的時候 記得兩點互聯 也就是這段
       graph = defaultdict(list)
       for edge in edges:
           u,v = edge[0], edge[1]
           graph[u].append(v)
           graph[v].append(u)




from collections import defaultdict
class Solution(object):
   def dfs(self, node, parent, graph, visited):
       visited.add(node)
       for nbr in graph[node]:
           if nbr not in visited:
               if self.dfs(nbr, node, graph, visited):
                   return True
           elif nbr in visited and nbr != parent:
               return True
       return False
   
   def validTree(self, n, edges):
       """
       :type n: int
       :type edges: List[List[int]]
       :rtype: bool
       """
       graph = defaultdict(list)
       for edge in edges:
           u,v = edge[0], edge[1]
           graph[u].append(v)
           graph[v].append(u)
       visited = set([])
       if self.dfs(0, -1, graph, visited): # check if there is a loop
           return False
       if len(visited) != n: # check if 連通
           return False
       return True

大神版解答:
思路: 樹的本值是連通並且無環 大神厲害就在這 用dict.pop() 判斷. 如果有環 就會出現有element 還在 neighbors裏頭 根據最後一行 and not neighbors 結果一定是 False.
判斷連通也是同樣的道理 如果全連通 則 neighbors 裡不會有任何的 elemen. 這裡可以說是一石二鳥.

def validTree(self, n, edges):
   # 建立鄰接表
   neighbors = {i: [] for i in range(n)}
   for v, w in edges:
       neighbors[v] += w,
       neighbors[w] += v,
   def visit(v):
       map(visit, neighbors.pop(v, []))
   visit(0)
   return len(edges) == n-1 and not neighbors

274. H-Index

思路: 引用次數 先由大到小排序 然後i >= cutations[i] 則返回 i

class Solution(object):
   def hIndex(self, citations):
       """
       :type citations: List[int]
       :rtype: int
       """
       citations.sort(reverse = True)
       for i in range(len(citations)):
           if i >= citations[i]:
               return i
       return len(citations)

117. Populating Next Right Pointers in Each Node II

思路: BFS 每層的treeNode 放入 list. 等掃完整層 就串接list裏頭的treeNode

# Definition for binary tree with next pointer.
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None

class Solution:
   # @param root, a tree link node
   # @return nothing
   def connect(self, root):
       q, path = [], []
       if not root: return root
       q.append(root)
       
       while q:
           path = []
           for i in range(len(q)):
               temp = q[0]
               del q[0]
               path.append(temp)
               if temp.left:  q.append(temp.left)
               if temp.right: q.append(temp.right)
           for j in range(len(path)):
               if j  != len(path)-1:
                   path[j].next = path[j+1]
           path[-1].next = None
       

275. H-Index II

思路: 二分搜索

class Solution(object):
   def hIndex(self, citations):
       """
       :type citations: List[int]
       :rtype: int
       """
       N = len(citations)
       low, high = 0, N - 1
       while low <= high:
           mid = (low + high) / 2
           if N - mid > citations[mid]:
               low = mid + 1
           else:
               high = mid - 1
       return N - low

208. Implement Trie (Prefix Tree)

思路: Trie 用在字串搜索很快, root 的健值為 空. TrieNode 的孩子用字典存取 增加速度

class TrieNode:
   # Initialize your data structure here.
   def __init__(self):
       self.children = dict()
       self.isWord = False
       
class Trie(object):

   def __init__(self):
       """
       Initialize your data structure here.
       """
       self.root = TrieNode()

   def insert(self, word):
       """
       Inserts a word into the trie.
       :type word: str
       :rtype: void
       """
       node = self.root
       for i in range(len(word)):
           if word[i] not in node.children:
               temp = TrieNode()
               node.children[word[i]] = temp
           node = node.children[word[i]]
       node.isWord = True

   def search(self, word):
       """
       Returns if the word is in the trie.
       :type word: str
       :rtype: bool
       """
       node = self.root
       for i in range(len(word)):
           if word[i] not in node.children:
               return False
           node = node.children[word[i]]
       return node.isWord

   def startsWith(self, prefix):
       """
       Returns if there is any word in the trie that starts with the given prefix.
       :type prefix: str
       :rtype: bool
       """
       node = self.root
       for i in range(len(prefix)):
           if prefix[i] not in node.children:
               return False
           node = node.children[prefix[i]]
       return True
       


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

554. Brick Wall

思路: 找出最少磚塊的一條線, 用字典來做. 要注意線不在左右兩邊

class Solution(object):
   def leastBricks(self, wall):
       """
       :type wall: List[List[int]]
       :rtype: int
       """
       res = {}
       
       for i in range(len(wall)):
           cnt = 0
           for j in range(len(wall[i])):
               res.setdefault(cnt,0)
               if cnt : res[cnt] += 1
               cnt += wall[i][j]
       return len(wall) - max(res.values()) or 0

Second try:


class Solution(object):
   def leastBricks(self, wall):
       """
       :type wall: List[List[int]]
       :rtype: int
       """
       hashmap = {}
       li = []
       for i in range(len(wall)):
           end = 0
           for j in range(len(wall[i])):
               end += wall[i][j]
               hashmap[end] = hashmap.get(end, 0) + 1
       for j in hashmap:
           li.append(hashmap[j])
       li.sort()
       if len(hashmap) <= 1:
           return len(wall)
       return li[-1] - li[-2]

525. Contiguous Array

思路: 用字典 並且起始值 {0 : -1}
我们需要用到一个trick,遇到1就加1,遇到0,就减1,这样如果某个子数组和为0,就说明0和1的个数相等,这个想法真是太叼了,不过博主木有想出来。知道了这一点,我们用一个哈希表建立子数组之和跟结尾位置的坐标之间的映射。如果某个子数组之和在哈希表里存在了,说明当前子数组减去哈希表中存的那个子数字,得到的结果是中间一段子数组之和,必然为0,说明0和1的个数相等,我们更新结果res,参见代码如下:

class Solution(object):
   def findMaxLength(self, nums):
       """
       :type nums: List[int]
       :rtype: int
       """
       res, dic, total = 0, {0: -1}, 0
       for i in range(len(nums)):
           total += 1 if nums[i] == 1 else -1
           if total in dic:
               res = max(res, i - dic[total])
           else:
               dic[total] = i
       return res
           

Second try:


class Codec:

   def serialize(self, root):
       """Encodes a tree to a single string.
       
       :type root: TreeNode
       :rtype: str
       """
       def doit(node):
           if node:
               vals.append(str(node.val))
               doit(node.left)
               doit(node.right)
           else:
               vals.append('#')
       vals = []
       doit(root)
       print vals
       return ' '.join(vals)

   def deserialize(self, data):
       def doit():
           i[0] += 1
           if vals[i[0]] == '#':
               return
           node = TreeNode(int(vals[i[0]]))
           node.left = doit()
           node.right = doit()
           return node
       vals = data.split()
       i = [-1]
       return doit()
       

       

523. Continuous Subarray Sum

思路: 這題要求不少 要注意條件.
  1. Sub-array 至少有兩個 element
  2. Sub-array 總和% k == 0
有好幾種做法, for, hash map, set

class Solution(object):
   def checkSubarraySum(self, nums, k):
       """
       :type nums: List[int]
       :type k: int
       :rtype: bool
       """
       for i in range(len(nums)):
           sum = nums[i]
           for j in range(i+1, len(nums)):
               sum += nums[j]
               if sum == k and j - i >= 1: return True
               if j - i >= 1 and k != 0 and sum % k == 0  : return True
       return False
       
DP:

O(n)就是一维DP.
假设A(0, i)区间存在k,使得[k, i]区间是以i结尾区间的最大值, 定义为Max[i], 在这里,当求取Max[i+1]时,
Max[i+1] = Max[i] + A[i+1],  if (Max[i] + A[i+1] >0)
               = 0, if(Max[i]+A[i+1] <0),如果和小于零,A[i+1]必为负数,没必要保留,舍弃掉
然后从左往右扫描,求取Max数字的最大值即为所求。


[Code]
1:    int maxSubArray(int A[], int n) {  
2:      // Start typing your C/C++ solution below  
3:      // DO NOT write int main() function  
4:      int sum = 0;  
5:      int max = INT_MIN;  
6:      for(int i =0; i < n ; i ++)  
7:      {  
8:        sum +=A[i];        
9:        if(sum>max)  
10:          max = sum;  
11:        if(sum < 0)  
12:          sum = 0;  
13:      }  
14:      return max;  
15:    }

621. Task Scheduler

思路: 只要求數字 而不是完整的結果

Let's say the most frequent tasks occur M times, and there are Mct of them.
When N > Mct, let's make our scheduling constraint strictly stronger by choosing N = Mct. So from now on, let's suppose Mct <= N, and the most frequent tasks are denoted #A, #B, #C, ... #K.
Then we could schedule say, ABC...K__...ABC...K_...ABC...K_....., where A...K occurs Mct times, _ denotes idle time, and there is Nspace between A's. This partial schedule would have length L = (M-1) * (N+1) + Mct. Clearly, we need at least L intervals of time in our schedule to fit our given tasks.


class Solution(object):
   def leastInterval(self, tasks, n):
       """
       :type tasks: List[str]
       :type n: int
       :rtype: int
       """
       task_counts = collections.Counter(tasks).values()
       M = max(task_counts)
       Mct = task_counts.count(M)
       return max(len(tasks), (M - 1) * (n + 1) + Mct)
       

210. Course Schedule II

思路: 拓譜排序, 先找出沒有入度的點  然後開始做dfs. 如果可以完成拓譜排序則 return res


# BFS
def findOrder1(self, numCourses, prerequisites):
   dic = {i: set() for i in xrange(numCourses)}
   neigh = collections.defaultdict(set)
   for i, j in prerequisites:
       dic[i].add(j)
       neigh[j].add(i)
   # queue stores the courses which have no prerequisites
   queue = collections.deque([i for i in dic if not dic[i]])
   count, res = 0, []
   while queue:
       node = queue.popleft()
       res.append(node)
       count += 1
       for i in neigh[node]:
           dic[i].remove(node)
           if not dic[i]:
               queue.append(i)
   return res if count == numCourses else []
   
# DFS
def findOrder(self, numCourses, prerequisites):
   dic = collections.defaultdict(set)
   neigh = collections.defaultdict(set)
   for i, j in prerequisites:
       dic[i].add(j)
       neigh[j].add(i)
   stack = [i for i in xrange(numCourses) if not dic[i]]
   res = []
   while stack:
       node = stack.pop()
       res.append(node)
       for i in neigh[node]:
           dic[i].remove(node)
           if not dic[i]:
               stack.append(i)
       dic.pop(node)
   return res if not dic else []

636. Exclusive Time of Functions

class Solution(object):
   def exclusiveTime(self, n, logs):
       """
       :type n: int
       :type logs: List[str]
       :rtype: List[int]
       """
       ans = [0] * n
       stack = []
       prev_time = 0

       for log in logs:
           fn, typ, time = log.split(':')
           fn, time = int(fn), int(time)

           if typ == 'start':
               if stack:
                   ans[stack[-1]] += time - prev_time
               stack.append(fn)
               prev_time = time
           else:
               ans[stack.pop()] += time - prev_time + 1
               prev_time = time + 1

       return ans

653. Two Sum IV - Input is a BST

# 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 findTarget(self, root, k):
       """
       :type root: TreeNode
       :type k: int
       :rtype: bool
       """
       def dfs(node):
           if not node: return
           if node.val not in dist : dist.append(node.val)
           if node.left:  dfs(node.left)
           if node.right: dfs(node.right)
               
       dist = []
       dfs(root)
       for i in dist:
           if k - i != i and k - i in dist: return True
       return False
   

15. 3Sum

思路: sort過後 雙指針

class Solution(object):
   def threeSum(self, nums):
       """
       :type nums: List[int]
       :rtype: List[List[int]]
       """
       res = []
       temp = []
       nums.sort()
       nl = len(nums)
       
       for i in range(nl):
           if i > 0 and nums[i] == nums[i-1]: continue
           #print i
           l, r = i +1 , nl - 1
           while l < r:
               s = nums[i] + nums[l] + nums[r]
               if s < 0:
                   l += 1
               elif s > 0:
                   r -= 1
               else:
                   res.append([nums[i], nums[l], nums[r]])
                   
                   while l < r and nums[l] == nums[l+1]:
                       l += 1
                   while l < r and nums[r] == nums[r-1]:
                       r -= 1
                   
                   l += 1
                   r -= 1
       return res

121. Best Time to Buy and Sell Stock

思路: buy = min(buy, i),  res = max(res, i - buy)

class Solution(object):
   def maxProfit(self, prices):
       """
       :type prices: List[int]
       :rtype: int
       """
       res, buy = 0, sys.maxint
       for i in prices:
           buy = min(buy, i)
           res = max(res, i - buy)
       return res

75. Sort Colors

思路: one approach, 雙指針交換, 如果nums[i] ==2 記得 i -= 1
Two approach, 統計0,1,2個數 然後返回 list

class Solution(object):
   def sortColors(self, nums):
       """
       :type nums: List[int]
       :rtype: void Do not return anything, modify nums in-place instead.
       """
       red, white, blue = 0, 0, 0
       for i in nums:
           if i == 0:   red   += 1
           elif i == 1: white += 1
           else: blue += 1

       for _ in range( red ):
           nums[_] = 0
       for _ in range( red,   red+white ):
           nums[_] = 1
       for _ in range( red+white, red+white+blue  ):
           nums[_] = 2

Second try:

class Solution(object):
   def sortColors(self, nums):
       i = 0
       for _ in range(len(nums)):
           if nums[i] == 0:
               nums.insert(nums.pop(i), 0)
               i += 1
           elif nums[i] == 2:
               nums.append(nums.pop(i))
           else:
               i += 1


78. Subsets

思路: dfs, path 持續加nums[j]

class Solution(object):
   def subsets(self, nums):
       """
       :type nums: List[int]
       :rtype: List[List[int]]
       """
       def dfs(i, path):
           res.append(path)
           for j in range(i,len(nums)):
               dfs(j+1, path+[nums[j]])
       
       res, path = [], []
       dfs( 0, path)
       return res

Second try: 更精煉一點的dfs

       def dfs(index, path):
           res.append(path)
           for i in range(index, len(nums)):
               dfs( i+1, path+[nums[i]] )
           
       res = []
       dfs(0, [])
       return res

79. Word Search

思路: dfs 向上下左右 四個方向搜索

class Solution(object):
   def exist(self, board, word):
       """
       :type board: List[List[str]]
       :type word: str
       :rtype: bool
       """
       if not board: return False
       
       m = len(board)
       n = len(board[0])
       path = []
       def dfs(i, j , w):
           # all the characters are checked
           if len(w) == 0: return True
           # check i, j not overboard
           if i<0 or i>=len(board) or j<0 or j>=len(board[0]) or w[0]!=board[i][j]:
                   return False
           tmp = board[i][j]  # first character is found, check the remaining part
           board[i][j] = "#"  # avoid visit agian
           # check whether can find "word" along one direction
           res = dfs( i+1, j, w[1:]) or dfs( i-1, j, w[1:]) \
           or dfs( i, j+1, w[1:]) or dfs( i, j-1, w[1:])
           board[i][j] = tmp
           return res

       for i in range(m):
           for j in range(n):
               if dfs(i, j, word):
                   return True
       return False
               

238. Product of Array Except Self

思路:
Input example = [1,2,3,4]
left = [1,1,2,6]
Result = result * left
左右兩個list 相乘

class Solution(object):
   def productExceptSelf(self, nums):
       """
       :type nums: List[int]
       :rtype: List[int]
       """
       n = len(nums)
       res = [1] * n
       left, right = 1, 1
       for i in range(1,n):
           left = left * nums[i-1]
           res[i] = left
       
       for j in range(n-2, -1, -1):
           right = right * nums[j+1]
           res[j] *= right
       return res
       

33. Search in Rotated Sorted Array

思路: 二分搜索. 作弊的方法是先 sort 之後再做二分搜索 但是這樣複雜度 從O(log n) 變成O(n log n) .  好的做法是直接在二分搜索裡判斷, 問題來了. 我們不知道 Array 是在哪裡 rotated的, 觀察一下 發現 如果 nums[mid] < nums[right] 則表示右半段是升續的, 相反的, 如果nums[mid] > nums[left] 就表示左半段是升續的.

class Solution(object):
   def search(self, nums, target):
       """
       :type nums: List[int]
       :type target: int
       :rtype: int
       """
       l, r = 0, len(nums)-1
       while l <= r:
           mid = (l+r) / 2
           if nums[mid] == target:
               return mid
           elif nums[mid] < nums[r]:
               if nums[mid] < target and nums[r] >= target: l = mid + 1
               else: r = mid -1
           else:
               if nums[mid] > target and nums[l] <= target: r = mid - 1
               else: l = mid + 1
       return -1

90. Subsets II

思路: 從combination 題的dfs裡得到靈感 要注意一定要 先sort

class Solution(object):
   def subsetsWithDup(self, nums):
       """
       :type nums: List[int]
       :rtype: List[List[int]]
       """
       nums.sort()
       def dfs(i, path):
           if path not in res:
               res.append(path[:])
           
           for _ in range(i,len(nums)):
               path.append(nums[_])
               dfs(_+1, path)
               path.pop()
           
       
       res, path = [], []
       if len(nums) == 0: return res
       elif len(nums) == 1: return [[],[nums[0]]]
       dfs(0, path)
       
       return res

380. Insert Delete GetRandom O(1)

思路: 設計題 用list.pop and index 來處理 remove

class RandomizedSet(object):

   def __init__(self):
       """
       Initialize your data structure here.
       """
       self.temp = []

   def insert(self, val):
       """
       Inserts a value to the set. Returns true if the set did not already contain the specified element.
       :type val: int
       :rtype: bool
       """
       if val not in self.temp:
           self.temp.append(val)
           return True
       else:
           return False

   def remove(self, val):
       """
       Removes a value from the set. Returns true if the set contained the specified element.
       :type val: int
       :rtype: bool
       """
       if val not in self.temp: return False
       else:
           self.temp.pop(self.temp.index(val))

           return True
       

   def getRandom(self):
       """
       Get a random element from the set.
       :rtype: int
       """
       if len(self.temp) == 1: return self.temp[0]
       if len(self.temp) == 0: return self.temp
       return self.temp[random.randint(0,len(self.temp)-1)]
       


# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()


88. Merge Sorted Array

思路: 但是还有更简洁的方法,而且不用申请新变量。算法思想是:由于合并后nums1数组的大小必定是m+n,所以从最后面开始往前赋值,先比较nums1和nums2中最后一个元素的大小,把较大的那个插入到m+n-1的位置上,再依次向前推。如果nums1中所有的元素都比nums2小,那么前m个还是A原来的内容,没有改变。如果nums1中的数组比nums2大的,当nums1循环完了,nums2中还有元素没加入nums1,直接用个循环把nums2中所有的元素覆盖到nums1剩下的位置

class Solution(object):
   def merge(self, nums1, m, nums2, n):
       """
       :type nums1: List[int]
       :type m: int
       :type nums2: List[int]
       :type n: int
       :rtype: void Do not return anything, modify nums1 in-place instead.
       """
       total = m + n - 1
       m -= 1
       n -= 1
       while m >= 0 and n >= 0:
           if nums1[m] > nums2[n]:
               nums1[total] = nums1[m]
               m -= 1
               total -= 1
           else:
               nums1[total] = nums2[n]
               n -= 1
               total -= 1
       while n >= 0:
           nums1[total] = nums2[n]
           n -= 1
           total -= 1
               

26. Remove Duplicates from Sorted Array

思路: 跟moving zero那題很像 都是宣告一個變數 如果當前的 i 不等於前一個 i 像則 交換 nums[count] = nums[i] 然後 count += 1

最後別忘了 return count += 1

class Solution(object):
   def removeDuplicates(self, nums):
       """
       :type nums: List[int]
       :rtype: int
       """
       count = 0
       n = len(nums)
       if len(nums) <= 1: return len(nums)
       for i in range(1,len(nums)):
           if nums[i] != nums[i-1]:
               count += 1
               nums[count] = nums[i]
       return count+1

80. Remove Duplicates from Sorted Array II

思路: 用list 來額外存結果, 可以出現兩次表示只有幾種情況可以append
  • 當前 i 跟前一項不一樣 , 直接append
  • 當前 i 跟前一項一樣 但不超過兩次, 直接append
class Solution(object):
   def removeDuplicates(self, nums):
       """
       :type nums: List[int]
       :rtype: int
       """
       temp = []
       before = None
       con = 1
       for i in nums:
           if i != before:
               temp.append(i)
               before = i
               con = 1
           elif con < 2:
               temp.append(i)
               con += 1
       nums[:len(temp)] = temp
       return len(temp)

69. Sqrt(x)

       left, right = 0, x/2 + 1
       while left <= right:
           mid = (left + right) / 2
           if mid * mid == x : return mid
           elif mid * mid < x : left = mid + 1
           elif mid * mid > x: right = mid - 1
       return right

168. Excel Sheet Column Title

       ref, res = [], []
       for i in range(65, 91):
           ref.append( str(unichr(i)) )

       while n:
           res.insert( 0, ref[(n-1)%26] )
           n = (n-1) // 26

       return "".join(res)

173. Binary Search Tree Iterator

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

class BSTIterator(object):
   def __init__(self, root):
       self.stack = []
       self.pushLeft(root)

   # @return a boolean, whether we have a next smallest number
   def hasNext(self):
       return self.stack

   # @return an integer, the next smallest number
   def next(self):
       top = self.stack.pop()
       self.pushLeft(top.right)
       return top.val
   
   def pushLeft(self, node):
       while node:
           self.stack.append(node)
           node = node.left

# Your BSTIterator will be called like this:
# i, v = BSTIterator(root), []
# while i.hasNext(): v.append(i.next())

572. Subtree of Another Tree

思路: same tree 進階版, 如果s, t 的root 一樣 直接call same tree function
如果s, t 的root 不一樣 遞迴check s的左子樹或右子樹 是不是跟t 一樣

class Solution(object):
   def isSubtree(self, s, t):
       """
       :type s: TreeNode
       :type t: TreeNode
       :rtype: bool
       """
       def dfs(p, q):
           if not p and not q: return True
           elif (p and not q) or (not p and q): return False
           elif (p.val != q.val): return False
           else:
               return dfs(q.left, p.left) and dfs(q.right, p.right)
       if not s: return False
       if (dfs(s, t)): return True
       return True if self.isSubtree(s.left, t) or self.isSubtree(s.right, t) else False

Second Try:
思路: dfs 遍歷 s 的左右子樹 如果s的某一節點 和t 是同樣的 return True else False

class Solution(object):
   def dfs(self, s, t):
       if not s : return False
       if self.isSameTree(s, t): self.ans = True
       self.dfs(s.left, t)
       self.dfs(s.right, t)
       
   def isSubtree(self, s, t):
       self.ans = False
       if not s: return False
       self.dfs(s, t)
       return self.ans
       
   def isSameTree(self, p, q):
       if p and not q: return False
       if q and not p: return False
       if not p and not q: return True
       if p.val != q.val: return False
       return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

543. Diameter of Binary Tree

思路: 左右子樹深度和 + 1. 我们只要对每一个结点求出其左右子树深度之和,再加上1就可以更新结果res了。

class Solution(object):
   def traverse(self, root):
       if not root: return 0
       left = self.traverse(root.left)
       right = self.traverse(root.right)
       self.ans = max(self.ans, left + right)
       return max(left, right) + 1

   def diameterOfBinaryTree(self, root):
       """
       :type root: TreeNode
       :rtype: int
       """
       self.ans = 0
       self.traverse(root)
       return self.ans

404. Sum of Left Leaves

思路: 遞迴尋找左葉節. 這裡的寫法很有趣

if l and (l.left or l.right) is None: 也等於  if l and l.left is None and r.right is None

class Solution(object):
   def sumOfLeftLeaves(self, root):
       ans = 0
       if root:
           l, r = root.left, root.right
           if l and (l.left or l.right) is None:
               ans += l.val
           lv = self.sumOfLeftLeaves(l)
           rv = self.sumOfLeftLeaves(r)
           ans += lv + rv
       return ans

200. Number of Islands

       if not grid : return 0
       m, n , res = len(grid), len(grid[0]), 0
       
       
       def dfs(i, j):
           grid[i][j] = 'P'
           if i > 0 and grid[i-1][j] == '1': dfs(i-1, j)
           if i < m - 1 and grid[i+1][j] == '1': dfs(i+1, j)
           if j > 0 and grid[i][j-1] == '1': dfs(i, j-1)
           if j < n - 1 and grid[i][j+1] == '1': dfs(i, j+1)
       
       for i in range(m):
           for j in range(n):
               if grid[i][j] == '1':
                   dfs(i,j)
                   res += 1
       return res
Second try:

class Solution(object):
   def numIslands(self, grid):
       """
       :type grid: List[List[str]]
       :rtype: int
       """
       def dfs(x, y):
           
           grid[x][y] = 'P'
           dic = ((1,0), (-1,0),(0,1),(0,-1))
           for _ in dic:
               if 0 <= x + _[0] < len(grid) and 0 <= y + _[1] < len(grid[0]) and grid[x+_[0]][y+_[1]] == '1' :
                   dfs(x + _[0], y + _[1])
       
       if not grid: return 0
       m = len(grid)
       n = len(grid[0])
       res = 0
       
       for i in range(m):
           for j in range(n):
               if grid[i][j] == '1':
                   dfs(i, j)
                   res += 1
       return res

133. Clone Graph

class Solution:
   # @param node, a undirected graph node
   # @return a undirected graph node
   def cloneGraph(self, node):
       def dfs(node, mapp):
           # check if node exist in the map
           if node in mapp: return mapp[node]
           # if node not in the map, copy it into the map
           output = UndirectedGraphNode(node.label)
           mapp[node] = output
           # handle the neighbor
           for i in node.neighbors:
               mapp[node].neighbors.append( dfs(i, mapp) )
           # don't forget to return
           return output
       
       if not node: return node
       return dfs(node, {})

278. First Bad Version


class Solution(object):
   def firstBadVersion(self, n):
       """
       :type n: int
       :rtype: int
       """
       if n == 1: return 1
       start, end = 1, n
       
       while start < end:
           mid = (start + end) / 2
           if isBadVersion(mid) == True:
               end = mid
           else:
               start = mid + 1
       return end

Second Try:

       l, r = 1 , n
       while l < r:
           mid = (l+r) / 2
           if isBadVersion(mid): r = mid
           else: l = mid + 1
       return r

461. Hamming Distance

class Solution(object):
   def hammingDistance(self, x, y):
       """
       :type x: int
       :type y: int
       :rtype: int
       """
       return bin(x ^ y).count('1')

477. Total Hamming Distance

class Solution(object):
   def totalHammingDistance(self, nums):
       """
       :type nums: List[int]
       :rtype: int
       """
       ans = 0
       mask = 1
       for i in range(32):
           zero, one = 0, 0
           for j in nums:
               if j & mask:
                   one += 1
               else:
                   zero += 1
           ans += zero * one
           mask = mask << 1
       return ans

67. Add Binary

class Solution(object):
   def addBinary(self, a, b):
       """
       :type a: str
       :type b: str
       :rtype: str
       """
       al, bl = len(a), len(b)
       flag = 0
       res = []
       i = 0
       a = a[::-1]
       b = b[::-1]
       while True:
           if i < al and i < bl :
               res.insert(0, str(int(a[i]) + int(b[i])) )
           elif i < al and i >= bl :
               res.insert(0, a[i] )
           elif i >= al and i < bl :
               print b[i]
               res.insert(0, b[i] )
           else:
               break
           i += 1
       
       print res
       # one shot handle overbit
       for i in range(len(res)-1, -1, -1):
           if int(res[i]) + flag > 1:
               res[i] = str((int(res[i]) + flag) % 2)
               flag = 1
           else:
               res[i] = str((int(res[i]) + flag))
               flag = 0
       
       if flag: res.insert(0,'1')
       return "".join(res)

Second try:   寫一個轉換成10進位的函數 把數字都換成10進位相加後 再換成2進位
       def strBintoint(s):
           res   = 0
           index = 0
           for i in range(len(s)-1,-1,-1):
               #print int(s[i]) * (2 ** index)
               res += int(s[i]) * (2 ** index)
               index += 1
           return res
       ab = strBintoint(a)
       bb = strBintoint(b)
       res = bin(ab + bb)
       return res[2:]


125. Valid Palindrome

class Solution(object):
   def isPalindrome(self, s):
       """
       :type s: str
       :rtype: bool
       """
       # handle corner case
       if len(s) <= 1 : return True
       # put s to lower
       s = s.lower()
       # create dictory
       dic = {}
       for i in range(65, 91):
           temp = str(unichr(i)).lower()
           dic[temp] = temp
       for i in range(0, 10):
           dic[str(i)] = str(i)
       # filter out non-char
       filt = []
       for j in s:
           if j in dic: filt.append(j)
       s = "".join(filt)
       # check if s is palindrome
       start, end = 0, len(s)-1
       while start <= end:
           if s[start] != s[end]:
               return False
           start += 1
           end   -= 1
       return True

49. Group Anagrams

class Solution(object):
   def groupAnagrams(self, strs):
       """
       :type strs: List[str]
       :rtype: List[List[str]]
       """
       res, dic = [], {}
       for i in strs:
           temp = "".join(sorted(i))
           if temp in dic:
               dic[temp].append(i)
           else:
               dic[temp] = [i]
       for j in dic:
           res.append(dic[j])
       return res
               

25. Reverse Nodes in k-Group

       dummy = p = ListNode(0)
       dummy.next = head
       n = 0
       while p.next:                   # find how many nodes we have in total
           p = p.next
           n += 1
       pre, p = dummy, dummy.next
       for j in range(n//k):           # we need n//k times reverse processes
           for i in range(k-1):
               print pre.val
               print p.val
               pre.next, p.next, pre.next.next = p.next, p.next.next, pre.next
           print
           pre, p = p, p.next          # set new "pre" and "p" node
       return dummy.next


301. Remove Invalid Parentheses

思路: BFS

class Solution(object):
   def removeInvalidParentheses(self, s):
       """
       :type s: str
       :rtype: List[str]
       """
       def isvalid(s):
           ans = 0
           for c in s:
               ans += {'(': 1, ')': -1}.get(c, 0)
               if ans < 0: return False
           return ans == 0
       res, visited, q, done = [], set([s]), [], False
       #visited[s] = True
       q.append(s)
       while q:
           t = q[0]
           del q[0]
           if isvalid(t):
               res.append(t)
               done = True
           if done: continue
           for i in range(len(t)):
               if t[i] not in {'(', ')'}: continue
               ne = t[:i] + t[i+1:]
               if ne not in visited:
                   visited.add(ne)
                   q.append(ne)
       return res
       

DFS:


class Solution(object):
   def check(self, s):
       c = 0
       for ch in s:
           if ch == '(': c += 1
           if ch == ')': c -= 1
               if c < 0: return False
       return c == 0
       
           
   def dfs(self, s, d_l, d_r, res, hist):
       if d_l == 0 and d_r == 0 :
          if not s in res and self.check(s):
               res[s] = True
       elif s == "":
           return
       else:
           for i in range(len(s)):
               if not s[0:i] + s[i+1:] in hist:
                   hist[s[0:i] + s[i+1:]] = True
                   
                   if s[i] == '(' and d_l > 0:
                       self.dfs(s[0:i] + s[i+1:], d_l-1, d_r, res, hist)
                       
                   if s[i] == ')' and d_r > 0:
                       self.dfs(s[0:i] + s[i+1:], d_l, d_r-1, res, hist)
                       
                   
   def removeInvalidParentheses(self, s):
   
       res = {}
       hist = {}
       d_r = 0 # number of '(' to be deleted
       d_l = 0 # number of ')' to be deleted
       for ch in s:
           if ch == '(':
               d_l += 1
           if ch == ')':
               if d_l > 0:
                   d_l -= 1
               else:
                   d_r += 1
   
       self.dfs(s, d_l, d_r, res, hist)
       
       return res.keys()


76. Minimum Window Substring

思路: 雙指針 一開始不斷往後移動尾指針
直到window 條件符合, 接者開始收縮頭指針
如果當前的window小於原來的window 就把他記起來

class Solution(object):
   def minWindow(self, s, t):
       need, missing = collections.Counter(t), len(t)
       i = I = J = 0
       for j, c in enumerate(s, 1):
           if need[c] > 0:
               missing -= 1                
           need[c] -= 1
           # find the windows
           if not missing:
               # shrink the window, keep move head
               while i < j and need[s[i]] < 0:
                   need[s[i]] += 1
                   i += 1
               # find the small window, save it
               if not J or j - i <= J - I:
                   I, J = i, j
       return s[I:J]


79. Word Search

思路: 對board裡的每個字母 做dfs
class Solution(object):
   def exist(self, board, word):
       """
       :type board: List[List[str]]
       :type word: str
       :rtype: bool
       """
       def find(i, j, word, idx):
           if idx==len(word): return True
           if 0<=i<len(board) and 0<=j<len(board[0]) and board[i][j]==word[idx]:
               temp, board[i][j] = board[i][j], '0'
               direction = ((1,0),(-1,0),(0,1),(0,-1))
               for x, y in direction:
                   if find(i+x,j+y,word,idx+1): return True
               board[i][j]=temp
           return False      
       
       for i in range(len(board)):
           for j in range(len(board[0])):
               if find(i,j,word,0):
                       return True
       return False

Replace %20

in-place replace all &quot;%20&quot; in a string to a space, ex:
abc%20def -&gt; abc def-google 1point3acres
abc%20%20%2 -&gt; abc  %2.

思路: O(n), n = len(s)

class Solution(object):
   def replace(self, s):
       y, write = 0, []
       for i in range(0, len(s)-3):
           if s[i:i+3] == "%20":
               write.append(i)
       write = write[::-1]
       for j in write:
           s = s[:j] + " " + s[j+3:]
       return s
       
ob = Solution()
print ob.replace("abc%20%20%2")


62. Unique Paths

思路: dp, 想法跟爬樓梯很像. 一個是一次只能走一格或兩格 另一個是 一次可以只能往右 或 往下

維護一個dp 一層一層掃
Your input
3
4
Your stdout
[1, 2, 1, 1]
[1, 2, 3, 1]
[1, 2, 3, 4]
[1, 3, 3, 4]
[1, 3, 6, 4]
[1, 3, 6, 10]
Your answer
10
Expected answer
10



class Solution(object):
   def uniquePaths(self, m, n):
       """
       :type m: int
       :type n: int
       :rtype: int
       """
       dp = [1] * n
       for i in range(1,m):
           for j in range(1,n):
               dp[j] += dp[j-1]
               print dp
       return dp[n-1]

63. Unique Paths II

思路: 也是用一維array 去掃, 遇到 grid[i][j] 等於 1 的時候就把 dp[j] 設為 0


class Solution(object):
   def uniquePathsWithObstacles(self, obstacleGrid):
       """
       :type obstacleGrid: List[List[int]]
       :rtype: int
       """
       if not obstacleGrid or not obstacleGrid[0]: return 0
       m = len(obstacleGrid)
       n = len(obstacleGrid[0])
       dp = [0] * n
       dp[0] = 1
       if obstacleGrid[0][0] == 1: return 0
       for i in range(m):
           for j in range(n):
               if (obstacleGrid[i][j] == 1): dp[j] = 0
               elif j > 0:                   dp[j] += dp[j-1]
               
       return dp[n-1]

367. Valid Perfect Square

class Solution(object):
   def isPerfectSquare(self, num):
       """
       :type num: int
       :rtype: bool
       """
       x = 1
       while x * x <= num:
           if x * x == num: return True
           x += 1
       return False

98. Validate Binary Search Tree

class Solution(object):
   def isValidBST(self, root):
       """
       :type root: TreeNode
       :rtype: bool
       """
       # do inorder
       def dfs(node):
           if not node: return
           dfs(node.left)
           res.append(node.val)
           dfs(node.right)
       res = []
       dfs(root)
       # cheak result
       if len(res) == 0 or len(res) == 1: return True
       for i in range(1,len(res)):
           if res[i-1] >= res[i]: return False
       return True


234. Palindrome Linked List

思路: 雙指針 後半段反轉 之後比較前後 兩段

class Solution(object):
   def isPalindrome(self, head):
       """
       :type head: ListNode
       :rtype: bool
       """
       if not head: return True
       slow = head
       fast = head

       while fast.next and fast.next.next:
           slow = slow.next
           fast = fast.next.next


       # reverse
       node = slow.next
       while node and node.next:
           ne = node.next
           node.next = ne.next
           ne.next = slow.next
           slow.next = ne
       # print second half
       while slow.next:
           slow = slow.next
           if slow.val != head.val: return False
           head = head.next
           

       return True

20. Valid Parentheses

思路: stack

class Solution(object):
   def isValid(self, s):
       """
       :type s: str
       :rtype: bool
       """
       left, right  = ['(','{','['],  [')','}',']']
       stack = []
       for i in s:
           if i in left:
               stack.append(i)
           if i in right:
               if stack and stack[-1] == left[right.index(i)]: stack.pop()
               else: return False
       return len(stack) == 0
           

1. Two Sum


       if not nums: return []
       res, dic = [], {}
       
       for i in range(len(nums)):
           if target - nums[i] in dic:
               res.append(dic[target - nums[i]])
               res.append(i)
           else:
               dic[nums[i]] = i
       return res

13. Roman to Integer

思路: 關鍵規則很簡單 判斷 s[i] 和 s[i-1].
如果s[i] <= s[i-1] : sum += s[i-1]
否則 sum -= s[i-1]
最後要記得sum要加上 s[-1]



class Solution(object):
   def romanToInt(self, s):
       """
       :type s: str
       :rtype: int
       """
       ROMAN = {
           'I': 1,
           'V': 5,
           'X': 10,
           'L': 50,
           'C': 100,
           'D': 500,
           'M': 1000
       }
       
       if s == "":
           return 0
           
       index = len(s) - 2
       sum = ROMAN[s[-1]]
       while index >= 0:
           if ROMAN[s[index]] < ROMAN[s[index + 1]]:
               sum -= ROMAN[s[index]]
           else:
               sum += ROMAN[s[index]]
           index -= 1
       return sum

273. Integer to English Words

思路: 遞迴 一層一層撥皮剝下去, 小於一千的都算好處理.

class Solution(object):
   def numberToWords(self, num):
       """
       :type num: int
       :rtype: str
       """
       to19 = 'One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve ' \
              'Thirteen Fourteen Fifteen Sixteen Seventeen Eighteen Nineteen'.split()
       tens = 'Twenty Thirty Forty Fifty Sixty Seventy Eighty Ninety'.split()
       def words(n):
           if n < 20:
               return to19[n-1:n]
           if n < 100:
               return [tens[n/10-2]] + words(n%10)
           if n < 1000:
               return [to19[n/100-1]] + ['Hundred'] + words(n%100)
           for p, w in enumerate(('Thousand', 'Million', 'Billion'), 1):
               if n < 1000**(p+1):
                   return words(n/1000**p) + [w] + words(n%1000**p)
       return ' '.join(words(num)) or 'Zero'

Flatten nested array

a = [[1]], [[[5]]]

def flatten(arr):
   res = []
   for i in range(len(arr)):
       if not isinstance(arr[i], list) :
           res.append(arr[i])
       else:
           res.extend(flatten(arr[i]))
   return res

print flatten(a)


309. Best Time to Buy and Sell Stock with Cooldown

思路:
这题比Best Time to Buy and Sell Stock II多了一个cooldown的条件,就变得麻烦多了。这题是一个多阶段优化问题,首先范围缩小到广搜,贪心或者动规。因为每步之间互相牵连,贪心显然不行。广搜固然可以,不过是O(2^n)复杂度,所以我们先考虑用动规。
对于每一天,有三种动作,buy, sell, cooldown, sell 和 cooldown 可以合并成一种状态,因为手里最终没有股票。最终需要的结果是 sell,即手里股票卖了获得最大利润。我们可以用两个数组来记录当前持股和未持股的状态,令sell[i] 表示第i天未持股时,获得的最大利润,buy[i]表示第i天持有股票时,获得的最大利润。
对于sell[i],最大利润有两种可能,一是今天没动作跟昨天未持股状态一样,二是今天卖了股票,所以状态转移方程如下:
sell[i] = max{sell[i - 1], buy[i-1] + prices[i]}
对于buy[i],最大利润有两种可能,一是今天没动作跟昨天持股状态一样,二是前天卖了股票,今天买了股票,因为 cooldown 只能隔天交易,所以今天买股票要追溯到前天的状态。状态转移方程如下:
buy[i] = max{buy[i-1], sell[i-2] - prices[i]}
最终我们要求的结果是sell[n - 1],表示最后一天结束时,手里没有股票时的最大利润。
这个算法的空间复杂度是O(n),不过由于sell[i]仅仅依赖前一项,buy[i]仅仅依赖前两项,所以可以优化到O(1)




class Solution(object):
   def maxProfit(self, prices):
       """
       :type prices: List[int]
       :rtype: int
       """
       if not prices: return 0
       
       sell = [0] * len(prices)
       buy  = [0] * len(prices)
       buy[0] = -prices[0]
       for i in range(1,len(prices)):
           sell[i] = max( sell[i-1], buy[i-1]  + prices[i] )
           buy[i]  = max( buy[i-1],  sell[i-2] - prices[i] )
       return sell[-1]


173. Binary Search Tree Iterator

思路:
题目大意:
实现一个二叉搜索树(BST)的迭代器。你的迭代器会使用BST的根节点初始化。
调用next()会返回BST中下一个最小的数字。
注意:next()和hasNext()应该满足平均O(1)时间复杂度和O(h)空间复杂度,其中h是树的高度。
解题思路:
维护一个栈,从根节点开始,每次迭代地将根节点的左孩子压入栈,直到左孩子为空为止。
调用next()方法时,弹出栈顶,如果被弹出的元素拥有右孩子,则以右孩子为根,将其左孩子迭代压栈。

class BSTIterator(object):
   def __init__(self, root):
       self.q = []
       self.pushLeft(root)

   def hasNext(self):
       return self.q
       
   def next(self):
       temp = self.q.pop()
       self.pushLeft(temp.right)
       return temp.val
   
   def pushLeft(self, node):
       while node:
           self.q.append(node)
           node = node.left

334. Increasing Triplet Subsequence

思路: 紀錄 最小點 a , 之後 b 如果match 就是True, else False

class Solution(object):
   def increasingTriplet(self, nums):

       a, b = sys.maxint, sys.maxint
       if len(nums) < 2: return False
       
       for i in range(len(nums)):
           if nums[i] <= a:
               a = nums[i]
           elif nums[i] <= b:
               b = nums[i]
           else:
               return True
       return False

留言