leetcode hard(一)

1. LRU Cache(https://oj.leetcode.com/problems/lru-cache/)

LRU最近最少使用,这里采用dict{}及双向列表(DoubleLinkedList), dict的pair{key, node}, node包含key, value, pre, pos。这样在set, get时找到key的时间复杂度都为O(1), 在set,get时要对操作的key进行更新,记录其被使用的时间,这里用双向列表实现,每个node在被使用后,到移到双向列表的表头,这样若cache满后,则从表尾删除node即可。

 1 class node:
 2   
 3   def __init__(self, key, value):
 4     self.val = value
 5     self.key = key
 6     self.pre = None
 7     self.next = None
 8 
 9 class Solution:
10 
11   def __init__(self, capacity):
12     self.capacity = capacity
13     self.dict = {}
14     self.head = node(-1, -1)
15     self.tail = node(-1, -1)
16     self.head.next = self.tail
17     self.tail.pre = self.head
18 
19   def get(self, key):
20     if key in self.dict:
21       value = self.dict[key]
22       value.pre.next = value.next
23       value.pre = self.head
24       value.next = self.head.next
25       self.head.next.pre = value
26       self.head.next = value
27       return value.val
28     else:
29       return -1
30   def set(self, key, value):
31     if key in self.dict:
32       v = self.dict[key]
33       v.val = value
34       v.pre.next = v.next
35       v.next = self.head.next
36       v.pre = self.head
37       self.head.next = v
38     else:
39       if self.capacity == 0:
40         n = self.tail.pre
41         n.pre.next = self.tail
42         self.tail.pre = n.pre
43         del self.dict[n.key]
44         del n
45         self.capacity += 1
46       self.capacity -= 1
47       newNode = node(key, value)
48       newNode.next = self.head.next
49       self.head.next = newNode
50       newNode.pre = self.head
51       newNode.next.pre = newNode
52       self.dict[key] = newNode

 2. Trapping Rain Water(https://oj.leetcode.com/problems/trapping-rain-water/)

解题思路:从左到右扫描一遍,记录每个bar左边最高的bar的高度。从右向左扫面一遍,边扫描边计算每个bar右边最高的bar的高度,得到min(maxLeft, maxRight),减去bar本身的高度,即为蓄水量。

 1   def trap(self, A):
 2     lenA = len(A)
 3     record = [0 for i in range(lenA)]
 4     max = 0
 5     for i in range(1, lenA):
 6       if max < A[i-1]:
 7         max = A[i-1]
 8       record[i] = max
 9     max = 0
10     area = 0
11     for i in range(lenA-1, -1, -1):
12       res = min(max, record[i])
13       if res > A[i]:
14         area += res - A[i]
15       if max < A[i]:
16         max = A[i]
17     return area

3. Max Points on a Line(https://oj.leetcode.com/problems/max-points-on-a-line/)

解题思路:斜率相同的点即在同一条直线上,这里算出每一个点与其它点组成直线的斜率,利用哈希映射,以斜率为key,value为key相同的点的值。需要特别考虑的是斜率为'inf'以及坐标相同的点。时间复杂度O(n^2)

 1   def maxPoints(self, points):
 2     res = -1
 3     l = len(points)
 4     if l == 0: return 0
 5     for i in range(l):
 6       slope = {'inf':0}
 7       sameNode = 1
 8       for j in range(l):
 9         if i == j:
10           continue
11         elif points[i].x == points[j].x and points[i].y != points[j].y:
12           slope['inf'] += 1
13         elif points[i].x != points[j].x:
14           tmp = 1.0*(points[i].y - points[j].y)/(points[i].x - points[j].x)
15           if tmp not in slope:
16             slope[tmp] = 1
17           else:
18             slope[tmp] += 1
19         else:
20           sameNode += 1
21       res = max(res, max(slope.values())+sameNode)
22     return res

4. Binary Tree Postorder Travel(https://oj.leetcode.com/problems/binary-tree-postorder-traversal/)

解法一:递归

 1   def pov(self, root):
 2     if root == None:
 3       return
 4     self.pov(root.left)
 5     self.pov(root.right)
 6     self.res.append(root.val)
 7 
 8   def postorderTraversal(self, root):
 9     self.res = []
10     self.pov(root)
11     return self.res

解法二:迭代方法:根节点,右子节点,左子节点依次进栈,若无左右子节点,则出栈,并且用pre记录此节点;后续若栈顶节点的左节点或右节点==prev或栈顶节点无左右子节点,则栈顶节点出栈。

 1   def postorderTraversal(self, root):
 2     stack = []
 3     res = []
 4     if root == None:
 5       return res
 6     stack.append(root)
 7     prev = None
 8     while stack:
 9       tmp = stack[len(stack)-1]
10       if (tmp.right == None and tmp.left == None) or (prev and (prev == tmp.left or prev == tmp.right)):
11         prev = tmp
12         res.append(tmp.val)
13         stack.pop()
14       else:
15         if tmp.right:
16           stack.append(tmp.right)
17         if tmp.left:
18           stack.append(tmp.left)
19     return res

5. Word BreakII(https://oj.leetcode.com/problems/word-break-ii/)

解题思路:需要枚举出所有可行的分割方式,这里需要使用dfs, 为了降低时间复杂度,需要剪枝,即使用动态规划来判断字符串是否可以被分割。

 1   def check(self, s, dict):
 2     dp = [False for i in range(len(s)+1)]
 3     dp[0] = True
 4     for i in range(1, len(s)+1):
 5       for j in range(0, i):
 6         if dp[j] and s[j:i] in dict:
 7           dp[i] = True
 8     return dp[len(s)]
 9 
10   def dfs(self, s, dict, valueList):
11     if self.check(s, dict):
12       if len(s) == 0:
13         self.res.append(valueList[1:])
14         return
15       for i in range(1, len(s)+1):
16         if s[:i] in dict:
17           self.dfs(s[i:], dict, valueList+ ' ' + s[:i])
18 
19 
20   def wordBreak(self, s, dict):
21     self.res = []
22     self.dfs(s, dict, '')
23     return self.res

6. Copy List with Random Pointer(https://oj.leetcode.com/problems/copy-list-with-random-pointer/)

解题思路:在每个node后复制一个node,复制的node的random指针指向它所复制的那个node的random指针所指向的节点的下一个节点。

 1   def copyRandomList(self, head):
 2     if head == None:
 3       return None
 4     tmp = head
 5     while tmp:
 6       node = RandomListNode(tmp.label)
 7       node.next = tmp.next
 8       tmp.next = node
 9       tmp = node.next
10 
11     tmp = head
12     while tmp:
13       if tmp.random:
14         tmp.next.random = tmp.random.next
15       tmp = tmp.next.next
16 
17     head2 = head.next
18     tmp1 = head
19     tmp2 = head.next
20     while tmp2.next:
21       tmp1.next = tmp2.next
22       tmp1 = tmp1.next
23       tmp2.next = tmp1.next
24       tmp2 = tmp2.next
25     tmp1.next = None
26     tmp2.next = None
27     return head2

 

posted @ 2014-10-29 22:31  darlwen  阅读(299)  评论(0编辑  收藏  举报