算法相关知识点
Classical Question
c1.Quick Sort / Top K problem
class Solution: """ @param n: An integer @param nums: An array @return: the Kth largest element """ def kthLargestElement(self, n, nums): # write your code here length = len(nums) if n>length or n==0: return None half_quicksort(nums,0,length-1) return nums[-n] def half_quicksort(nums,start,end): if start<end: left,right=start,end pivot = nums[start] while left<right: while left<right and nums[right]>=pivot: right-=1 nums[left],nums[right]=nums[right],nums[left] while left<right and nums[left]<pivot: left+=1 nums[left],nums[right]=nums[right],nums[left] half_quicksort(nums,right+1,end) half_quicksort(nums,start,right-1)
class Solution: """ @param n: An integer @param nums: An array @return: the Kth largest element """ #方法二,利用二叉堆 def kthLargestElement2(self, n, nums): import heapq length = len(nums) if n>length or n==0: return None return heapq.nlargest(n,nums)[n-1]
思路: 快速选择算法 的平均时间复杂度为 O(N){O}(N)O(N)。就像快速排序那样,本算法也是 Tony Hoare 发明的,因此也被称为 Hoare选择算法。 """ 本方法大致上与快速排序相同。简便起见,注意到第 k 个最大元素也就是第 N - k 个最小元素,因此可以用第 k 小算法来解决本问题。 首先,我们选择一个枢轴,并在线性时间内定义其在排序数组中的位置。这可以通过 划分算法 的帮助来完成。 为了实现划分,沿着数组移动,将每个元素与枢轴进行比较,并将小于枢轴的所有元素移动到枢轴的左侧。 这样,在输出的数组中,枢轴达到其合适位置。所有小于枢轴的元素都在其左侧,所有大于或等于的元素都在其右侧。 这样,数组就被分成了两部分。如果是快速排序算法,会在这里递归地对两部分进行快速排序,时间复杂度为 O(NlogN)。 而在这里,由于知道要找的第 N - k 小的元素在哪部分中,我们不需要对两部分都做处理,这样就将平均时间复杂度下降到 O(N)。 """ class Solution: """ @param n: An integer @param nums: An array @return: the Kth largest element """ def kthLargestElement(self, n, nums): # write your code here length = len(nums) if n>length or n==0: return None return half_quicksort(nums,n,0,length-1) def half_quicksort(nums,k,start,end): if k==1 and start==end: return nums[start] if start<end: left,right=start,end pivot = nums[start] while left<right: while left<right and nums[right]>=pivot: right-=1 nums[left],nums[right]=nums[right],nums[left] while left<right and nums[left]<pivot: left+=1 nums[left],nums[right]=nums[right],nums[left] if end-right>k-1: return half_quicksort(nums,k,right+1,end) elif end-right<k-1: return half_quicksort(nums,k-(end-right+1),start,right-1) else: return nums[right]
c2.Binary Search
Closest K Elements:
https://www.lintcode.com/problem/k-closest-points/description
class Solution: """ @param A: an integer array @param target: An integer @param k: An integer @return: an integer array """ def kClosestNumbers(self, A, target, k): # write your code here sub=100000 nearest=-1 start = 0 end = len(A)-1 while start<=end: mid = (start+end)//2 temp = abs(A[mid]-target) if temp<sub: sub = temp nearest = mid if A[mid]>target: end = mid-1 elif A[mid]<target: start = mid+1 elif A[mid]==target: break out=[] if nearest!=-1 and k>0: out.append(A[nearest]) i=1 left,right=nearest-1,nearest+1 while left>=0 and right<=len(A)-1 and i<k: if abs(A[left]-target)<=abs(A[right]-target): out.append(A[left]) left = left-1 else: out.append(A[right]) right = right+1 i = i+1 if i<k and left<0: out.extend(A[right:right+k-i]) if i<k and right>len(A)-1: out.extend(A[left:left-(k-i):-1]) return out if __name__=="__main__": s = Solution() print(s.kClosestNumbers( A = [1, 2, 3], target = 2, k = 3)) print(s.kClosestNumbers(A = [1, 4, 6, 8], target = 3, k = 3)) print(s.kClosestNumbers(A = [1,4,6,10,20], target = 21, k = 4)) print(s.kClosestNumbers(A = [1,2,4,5,6,7,8,10], target = 5, k = 0)) print(s.kClosestNumbers(A = [1,4,8,12,16,28,38], target = 12, k = 4)) print(s.kClosestNumbers(A = [1,4,6,8], target = 3, k = 3))
https://www.lintcode.com/problem/k-closest-points/description
""" Definition for a point. class Point: def __init__(self, a=0, b=0): self.x = a self.y = b """ class Solution: """ @param points: a list of points @param origin: a point @param k: An integer @return: the k closest points """ def kClosest(self, points, origin, k): # write your code here import heapq ret = [] if len(points)==0 or k<0 or k>len(points): return ret hp = [] for point in points: dis = (point.x-origin.x)*(point.x-origin.x) + (point.y-origin.y)*(point.y-origin.y) heapq.heappush(hp, [dis, point.x, point.y]) for i in range(k): _, x, y = heapq.heappop(hp) ret.append([x, y]) return ret
C3. Binary Tree Traversal
Zigzag order
https://www.lintcode.com/problem/binary-tree-zigzag-level-order-traversal/description
class Solution: """ @param root: A Tree @return: A list of lists of integer include the zigzag level order traversal of its nodes' values. """ def zigzagLevelOrder(self, root): # write your code here ret = [] if not root or not root.val: return ret q = [[root]] i = 0 while q: temp = [] val = [] cur = q.pop(0) for node in cur: val.append(node.val) if node.left: temp.append(node.left) if node.right: temp.append(node.right) if i&1: val = val[::-1] if temp: q.append(temp) ret.append(val) i += 1 return ret
right-view
https://www.lintcode.com/problem/binary-tree-right-side-view/description
""" Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None """ class Solution: """ @param root: the root of the given tree @return: the values of the nodes you can see ordered from top to bottom """ def rightSideView(self, root): # write your code here ret = [] if not root or not root.val: return ret q = [[root]] while q: temp = [] cur = q.pop(0) for node in cur: if node.left: temp.append(node.left) if node.right: temp.append(node.right) ret.append(node.val) if temp: q.append(temp) return ret
Balanced search tree validation
https://www.lintcode.com/problem/balanced-binary-tree/description
""" Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None """ class Solution: """ @param root: The root of binary tree. @return: True if this Binary tree is Balanced, or false. """ def isBalanced(self, root): # write your code here balanced, _ = self.cal_balance(root) return balanced def cal_balance(self, node): if node==None: return True, 0 balanced, leftHeight = self.cal_balance(node.left) if not balanced: return False, 0 balanced, rightHeight = self.cal_balance(node.right) if not balanced: return False, 0 diff = abs(leftHeight-rightHeight) return diff<=1, max(leftHeight, rightHeight)+1
Binary search tree validation
https://www.lintcode.com/problem/validate-binary-search-tree/description
#coding:utf-8 """ 95. Validate Binary Search Tree Description Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys greater than the node's key. Both the left and right subtrees must also be binary search trees. A single node tree is a BST Example 1: Input: {-1} Output:true Explanation: For the following binary tree(only one node): -1 This is a binary search tree. Example 2: Input: {2,1,4,#,#,3,5} Output: true For the following binary tree: 2 / \ 1 4 / \ 3 5 This is a binary search tree. """ #中序遍历,挨个比较大小 """ Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None """ class Solution: """ @param root: The root of binary tree. @return: True if the binary tree is BST, or false """ def isValidBST(self, root): # write your code here if root==None: return True self.valid=True self.lastVal=None self.helper(root) return self.valid def helper(self,node): if node==None: return self.helper(node.left) if self.lastVal!=None and self.lastVal>=node.val: self.valid=False return self.lastVal=node.val self.helper(node.right)
C4.Linked List
https://www.cnblogs.com/silence-cho/p/10041616.html
Reverse Linked list
https://www.lintcode.com/problem/reverse-linked-list-ii/description
class Solution: """ @param head: ListNode head is the head of the linked list @param m: An integer @param n: An integer @return: The head of the reversed ListNode """ def reverseBetween(self, head, m, n): # write your code here if not head or m<1 or n<1 or m>=n: return head start = head pre_start = start while m != 1 and start: pre_start = start start = start.next m -= 1 n -= 1 if m>1: return head pre = start cur = pre.next n -= 1 while n !=1 and cur: temp = cur.next cur.next = pre pre = cur cur = temp n -= 1 if n>1: return head start.next = cur.next cur.next = pre if start!=head: pre_start.next = cur else: head = cur return head
https://www.lintcode.com/problem/reverse-linked-list/description
#coding:utf-8 """ 35. Reverse Linked List Reverse a linked list. Example Example 1: Input: 1->2->3->null Output: 3->2->1->null Example 2: Input: 1->2->3->4->null Output: 4->3->2->1->null Challenge Reverse it in-place and in one-pass """ """ Definition of ListNode class ListNode(object): def __init__(self, val, next=None): self.val = val self.next = next """ class Solution: """ @param head: n @return: The new head of reversed linked list. """ def reverse(self, head): # write your code here if not head: return head pre = head cur = head.next while cur: temp = cur.next cur.next = pre pre = cur cur = temp head.next = cur return pre #递归法 class Solution: """ @param head: n @return: The new head of reversed linked list. """ def reverse(self, head): # write your code here if not head or not head.next: return head else: newhead = self.reverse(head.next) head.next.next = head head.next = None return newhead
Merge two linked list
https://www.lintcode.com/problem/merge-two-sorted-lists/description
#coding:utf-8 """ 165. Merge Two Sorted Lists Merge two sorted (ascending) linked lists and return it as a new sorted list. The new sorted list should be made by splicing together the nodes of the two lists and sorted in ascending order. Example Example 1: Input: list1 = null, list2 = 0->3->3->null Output: 0->3->3->null Example 2: Input: list1 = 1->3->8->11->15->null, list2 = 2->null Output: 1->2->3->8->11->15->null """ """ Definition of ListNode class ListNode(object): def __init__(self, val, next=None): self.val = val self.next = next """ class Solution: """ @param l1: ListNode l1 is the head of the linked list @param l2: ListNode l2 is the head of the linked list @return: ListNode head of linked list """ def mergeTwoLists(self, l1, l2): # write your code here if not l1: return l2 if not l2: return l1 if not l1 and not l2: return None if l1.val<=l2.val: head = l1 l1 = l1.next else: head = l2 l2 = l2.next temp = head while l1 and l2: if l1.val <= l2.val: temp.next = l1 l1 = l1.next else: temp.next = l2 l2 = l2.next temp = temp.next if l1: temp.next = l1 if l2: temp.next = l2 return head
C5. Sqrt / Pow
Binary Search / Newton
https://www.lintcode.com/problem/sqrtx/description
#coding:utf-8 """ 141. Sqrt(x) Implement int sqrt(int x). Compute and return the square root of x. Example Example 1: Input: 0 Output: 0 Example 2: Input: 3 Output: 1 Explanation: return the largest integer y that y*y <= x. Example 3: Input: 4 Output: 2 Challenge O(log(x)) """ #参考:https://www.jiuzhang.com/solutions/sqrtx/ class Solution: """ @param x: An integer @return: The sqrt of x """ def sqrt(self, x): # write your code here if x==0 or x==1: return x low, high = 1, x while low+1<high: mid = (low+high)//2 #防止溢出 if (x//mid>mid): low = mid elif (x//mid < mid): high = mid else: return mid if x//high < high: return low return high #牛顿法 """ 牛顿迭代法。令t = sqrt(x), 根据 x = sqrt(x) * sqrt(x)构造不动点 n = t * t n + t * t = 2 * t * t (n / t) + t = 2 * t t = (n / t + t) / 2 """ class Solution: """ @param x: An integer @return: The sqrt of x """ def sqrt(self, x): # write your code here if x==0 or x==1: return x guess = 1 while (abs(x/guess - guess)>0.1): guess = (x/guess +guess)/2 return int(guess)
Recursive / Bit Operation
https://www.lintcode.com/problem/power-of-two/description
#coding:utf-8 """ 1314. Power of Two Given an integer, write a function to determine if it is a power of two. Example Example Input: n = 3 Output: false """ #2的幂次方,比特位数中只有一位是1,其他全是0。(也可以遍历判断是不是只有一位是1) #比特操作 class Solution: """ @param n: an integer @return: if n is a power of two """ def isPowerOfTwo(self, n): # Write your code here if n<=0: return False flag = n&(n-1) return flag==0 # class Solution: """ @param n: an integer @return: if n is a power of two """ def isPowerOfTwo(self, n): # Write your code here if n<=0: return False while n>1: n = n/2 if int(n)!=n: return False return True #递归 class Solution: """ @param n: an integer @return: if n is a power of two """ def isPowerOfTwo(self, n): # Write your code here if n<=0: return False # if int(n) != n: # return False if n==1: return True return self.isPowerOfTwo(n/2)
C6.Points minimum distance in a matrix
Binary maze (迷宫问题)
给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem)。
迷宫可以以二维数组来存储表示。0表示通路,1表示障碍。注意这里规定移动可以从上、下、左、右四方方向移动。坐标以行和列表示,均从0开始,给定起点(0,0)和终点(4,4),迷宫表示如下:
-
maze[5][5]={
-
{0,0,0,0,0},
-
{0,1,0,1,0},
-
{0,1,1,0,0},
-
{0,1,1,0,1},
-
{0,0,0,0,0}
-
};
那么下面的迷宫就有两条可行的路径,分别为:
(1)(0,0) (0,1) (0,2) (0,3) (0,4) (1,4) (2,4) (2,3) (3,3) (4,3) (4,4);
(2)(0,0) (1,0) (2,0) (3,0) (4,0) (4,1) (4,2) (4,3) (4,4) ;
可见,迷宫可行路径有可能是多条,且路径长度可能不一。
#coding:utf-8 #binary maze (迷宫问题) """ 给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem)。 迷宫可以以二维数组来存储表示。0表示通路,1表示障碍。注意这里规定移动可以从上、下、左、右四方方向移动。坐标以行和列表示,均从0开始,给定起点(0,0)和终点(4,4),迷宫表示如下: [ [ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 ], [ 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 ], [ 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], [ 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 ], [ 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 ], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], [ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 ], [ 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 ] ] """ def find_shortest_path(maze, start, destination): if len(maze)==0 or len(maze[0])==0: return None row, col = len(maze), len(maze[0]) if start[0]<0 or start[0]>=row or start[1]<0 or start[1]>=col or destination[0]<0 or destination[0]>=row or destination[1]<0 or destination[1]>=col: return None visited = [[-1]*col for i in range(row)] #存储路径长度 pre = [[0]*col for i in range(row)] #存储前节点 q = [start] visited[start[0]][start[1]] += 1 path = [] direction = [[-1, 0], [0, 1], [0, -1], [1, 0]] while q: cur = q.pop(0) if cur==destination: path_length = visited[cur[0]][cur[1]] path.append(destination) temp = pre[destination[0]][destination[1]] while temp!=start: path.append(temp) temp = pre[temp[0]][temp[1]] path.append(start) path.reverse() return path_length, path for i in direction: next = [cur[0]+i[0], cur[1]+i[1]] if next[0]<0 or next[0]>=row or next[1]<0 or next[1]>=col or visited[next[0]][next[1]]!=-1 or maze[next[0]][next[1]]==1: #越界, 有障碍或已访问,舍去 continue else: visited[next[0]][next[1]] = visited[cur[0]][cur[1]] + 1 pre[next[0]][next[1]] = cur q.append(next) return None if __name__ == "__main__": maze = [ [ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 ], [ 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 ], [ 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], [ 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 ], [ 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 ], [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], [ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 ], [ 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 ] ] # start, end = [1, 1], [1, 3] start, end = [4, 9], [7, 1] ret = find_shortest_path(maze, start, end) if ret: print(ret)
Normal maze
给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem)。
迷宫可以以二维数组来存储表示。
坐标以行和列表示,均从0开始,如起点(0,0)和终点(4,4)
移动可以从上、下、左、右四方方向移动,数字表示上下左右邻节点到该点的距离,迷宫表示如下:
(Normal maze和Binary maze唯一的区别在于,矩阵中的数字表示邻节点到该节点的距离)
[
[ 1, 1, 1, 1],
[ 2, 3, 3, 4],
]
#coding:utf-8 #Normal maze (迷宫问题) """ 给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem)。 迷宫可以以二维数组来存储表示。 坐标以行和列表示,均从0开始,如起点(0,0)和终点(4,4) 移动可以从上、下、左、右四方方向移动,数字表示上下左右邻节点到该点的距离,迷宫表示如下: (Normal maze和Binary maze唯一的区别在于,矩阵中的数字表示邻节点到该节点的距离) [ [ 1, 1, 1, 1], [ 2, 3, 3, 4], ] """ #normal maze import heapq def find_shortest_path(maze, start, end): if len(maze)==0 or len(maze[0])==0: return None row, col = len(maze), len(maze[0]) if start[0]<0 or start[0]>=row or start[1]<0 or start[1]>=col or end[0]<0 or end[0]>=row or end[1]<0 or end[1]>=col: return None visited = [[0]*col for i in range(row)] #存储是否访问 pre = [[0]*col for i in range(row)] #存储前节点 direction = [[-1, 0], [0, 1], [0, -1], [1, 0]] path = [] q = [] heapq.heappush(q, [0, start]) #存储所有节点到起点的距离 visited[start[0]][start[1]] = 1 while q: cur = heapq.heappop(q) if cur[1] == end: shortest_distance = cur[0] path.append(end) temp = pre[end[0]][end[1]] while temp!= start: path.append(temp) temp = pre[temp[0]][temp[1]] path.append(temp) path.reverse() return shortest_distance, path for i in direction: next = [cur[1][0]+i[0], cur[1][1]+i[1]] if 0<=next[0]<row and 0<=next[1]<col and visited[next[0]][next[1]] == 0: visited[next[0]][next[1]] = 1 pre[next[0]][next[1]] = cur[1] dis = cur[0] + maze[next[0]][next[1]] heapq.heappush(q, [dis, next]) return None if __name__ == "__main__": maze = [ [ 1, 1, 1, 1], [ 2, 3, 3, 4], ] # start, end = [1, 0], [1, 3] start, end = [0, 3], [1, 0] ret = find_shortest_path(maze, start, end) if ret: print(ret)
C7. Number Island I&II
https://www.lintcode.com/problem/number-of-islands/description
#coding:utf-8 """ 433. Number of Islands Given a boolean 2D matrix, 0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent. Find the number of islands. Example Example 1: Input: [ [1,1,0,0,0], [0,1,0,0,1], [0,0,0,1,1], [0,0,0,0,0], [0,0,0,0,1] ] Output:3 Example 2: Input: [ [1,1] ] Output:1 """ """ 思路:线性扫描整个二维网格,如果一个结点包含 1,则以其为根结点启动深度优先搜索。在深度优先搜索过程中,每个访问过的结点被标记为 0。计数启动深度优先搜索的根结点的数量,即为岛屿的数量。 """ class Solution: """ @param grid: a boolean 2D matrix @return: an integer """ def numIslands(self, grid): # write your code here rows = len(grid) nums = 0 if rows==0: return nums for r in range(rows): cols = len(grid[r]) if cols>0: for c in range(cols): if grid[r][c]==1: dfs(grid,r,c) nums+=1 return nums def dfs(grid,r,c): rows = len(grid) if r<0 or r>rows-1: return cols = len(grid[r]) if c<0 or c>cols-1: return if grid[r][c]==0: return grid[r][c]=0 #grid[r][c]=1,将其由1设置为0,表示已经遍历 dfs(grid,r-1,c) dfs(grid,r+1,c) dfs(grid,r,c-1) dfs(grid,r,c+1) # class Solution: # """ # @param grid: a boolean 2D matrix # @return: an integer # """ # def numIslands(self, grid): # # write your code here # if len(grid)==0 or len(grid[0])==0: # return 0 # row, col = len(grid), len(grid[0]) # count = 0 # for i in range(row): # for j in range(col): # if grid[i][j]==1: # count+=1 # self.dfs(grid, i, j, row, col) # return count # def dfs(self, grid, i, j, row, col): # direction = [[-1, 0], [1, 0], [0, -1], [0, 1]] # q = [[i, j]] # grid[i][j] = 0 # while q: # cur = q.pop() # for item in direction: # x = cur[0] + item[0] # y = cur[1] + item[1] # if 0<=x<row and 0<=y<col and grid[x][y]==1: # q.append([x, y]) # grid[x][y] = 0 if __name__=="__main__": s = Solution() g1 =[ [1,1,0,0,0], [0,1,0,0,1], [0,0,0,1,1], [0,0,0,0,0], [0,0,0,0,1] ] g2=[ [1,1] ] print(s.numIslands(g1)) print(s.numIslands(g2))
#coding:utf-8 """ 434. Number of Islands II Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator. Example Example 1: Input: n = 4, m = 5, A = [[1,1],[0,1],[3,3],[3,4]] Output: [1,1,2,2] Explanation: 0. 00000 00000 00000 00000 1. 00000 01000 00000 00000 2. 01000 01000 00000 00000 3. 01000 01000 00000 00010 4. 01000 01000 00000 00011 Example 2: Input: n = 3, m = 3, A = [[0,0],[0,1],[2,2],[2,1]] Output: [1,1,2,2] Notice 0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent. """ #解决方法:并查集 #参考:https://zhuanlan.zhihu.com/p/54567565 #参考:https://zhuanlan.zhihu.com/p/55604968 """ Definition for a point. class Point: def __init__(self, a=0, b=0): self.x = a self.y = b """ class UnionFindSet: def __init__(self, m, n): self.table = [i for i in range(m*n)] def find_root(self, x): if self.table[x] != x: return self.find_root(self.table[x]) return self.table[x] def merge(self, x, y): x_root = self.find_root(x) y_root = self.find_root(y) self.table[x_root] = y_root class Solution: """ @param n: An integer @param m: An integer @param operators: an array of point @return: an integer array """ def numIslands2(self, n, m, operators): # write your code here if n==0 or m==0 or len(operators)==0: return [] def idx(i, j): return i*m +j direction = [[-1, 0], [1, 0], [0, 1], [0, -1]] ret = [] count = 0 matrix = [[0]*m for i in range(n)] us = UnionFindSet(m, n) for item in operators: if matrix[item.x][item.y]!=1: count += 1 matrix[item.x][item.y] = 1 for neb in direction: r = item.x+neb[0] c = item.y+neb[1] if 0<=r<n and 0<=c<m and matrix[r][c]==1: #附近位置为岛屿时,需要进一步判断,是否该减去之前加上的1 x1 = idx(item.x, item.y) x2 = idx(r, c) if us.find_root(x1) != us.find_root(x2): #如果与附近节点不属于同一片岛屿,需要减1 count-=1 us.merge(x1, x2) ret.append(count) return ret
并查集:
#参考:https://zhuanlan.zhihu.com/p/54567565
#参考:https://zhuanlan.zhihu.com/p/55604968
C8. Other Regular Problems
Best time to buy and sell stock
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock/description
class Solution: """ @param prices: Given an integer array @return: Maximum profit """ import sys def maxProfit(self, prices): # write your code here if len(prices)==0: return 0 min_price = sys.maxsize max_profit = 0 for price in prices: min_price = min(min_price, price) profit = price - min_price max_profit = max(max_profit, profit) return max_profit
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-ii/description
class Solution: """ @param prices: Given an integer array @return: Maximum profit """ def maxProfit(self, prices): # write your code here size = len(prices) if size<=1: return 0 res = 0 for i in range(1, size): if prices[i]>prices[i-1]: res += prices[i]-prices[i-1] return res
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-iii/description
#coding:utf-8 """ 151. Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Example Example 1 Input : [4,4,6,1,1,4,2,5] Output : 6 Notice You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). """ #思路:动态规划 #参考:https://blog.csdn.net/linhuanmars/article/details/23236995 class Solution: """ @param prices: Given an integer array @return: Maximum profit """ def maxProfit(self, prices): # write your code here size = len(prices) if size<=1: return 0 local_ = [0]*3 global_ = [0]*3 for i in range(1, size): diff = prices[i]-prices[i-1] for j in range(2, 0, -1): local_[j] = max(global_[j-1]+max(diff, 0), local_[j]+diff) global_[j] = max(local_[j], global_[j]) return global_[-1] #参考:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/solution/yi-ge-tong-yong-fang-fa-tuan-mie-6-dao-gu-piao-wen/ class Solution: """ @param prices: Given an integer array @return: Maximum profit """ def maxProfit(self, prices): # write your code here if not prices: return 0 size = len(prices) k=2 dp_buy = [[0]*(k+1) for i in range(size)] dp_sale = [[0]*(k+1) for i in range(size)] for i in range(size): for j in range(k, 0, -1): if i==0: dp_buy[i][j]=-prices[i] else: dp_sale[i][j] = max(dp_sale[i-1][j], dp_buy[i-1][j]+prices[i]) dp_buy[i][j] = max(dp_buy[i-1][j], dp_sale[i-1][j-1]-prices[i]) return dp_sale[size-1][k]
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-iv/description
#coding:utf-8 """ 393. Best Time to Buy and Sell Stock IV Given an array prices and the i-th element of it represents the price of a stock on the i-th day. You may complete at most k transactions. What's the maximum profit? Example Example 1: Input: k = 2, prices = [4, 4, 6, 1, 1, 4, 2 ,5] Output: 6 Explanation: Buy at 4 and sell at 6. Then buy at 1 and sell at 5. Your profit is 2 + 4 = 6. Example 2: Input: k = 1, prices = [3, 2, 1] Output: 0 Explanation: No transaction. Challenge O(nk) time. n is the size of prices. Notice You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again). """ #Best Time to Buy and Sell Stock II 和Best Time to Buy and Sell Stock III的综合 class Solution: """ @param K: An integer @param prices: An integer array @return: Maximum profit """ def maxProfit(self, K, prices): # write your code here size = len(prices) if size<=1 or K==0: return 0 if K>=size: return self.multi_transcation(prices) else: local_ = [0]*(K+1) global_ = [0]*(K+1) for i in range(1, size): diff = prices[i]-prices[i-1] for j in range(K, 0, -1): local_[j] = max(global_[j-1]+max(diff, 0), local_[j]+diff) global_[j] = max(local_[j], global_[j]) return global_[-1] def multi_transcation(self, prices): res = 0 for i in range(1, len(prices)): if prices[i]>prices[i-1]: res += prices[i]-prices[i-1] return res
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-with-transaction-fee/description
I added some notes below to help me understand it: Only 1 share of the stock can be bought or sold; A stock can be bought or sold for multiple times in one day, but it has to be sold before being bought again; The service fee is only charged when stock is sold; Cash(i): the cash in hand, if you are not holding the stock at the end of day(i): You might be not holding the stock at the end of day(i-1), and do nothing in day(i): a = cash(i-1); or You might be holding the stock at the end of day(i-1), and sell it at the end of day(i): b = hold(i-1) + prices[i] - fee; Choose the greatest one as the value of cash(i) to get the greater potential profit: cash(i) = max(a, b) = max(cash(i-1), hold(i-1) + prices[i] - fee); Hold(i): the cash in hand, if you are holding the stock at the end of day(i): You might be holding the stock at the end of day(i-1), and do nothing in day(i): a = hold(i-1); or You might be not holding the stock at the end of day(i-1), and buy it at the end of day(i): b = cash(i-1) - prices[i]; or You might be holding the stock at the end of day(i-1), sell it on day(i), and buy it again at the end of day(i): c = (hold(i-1) + prices[i] - fee) - prices[i]; Choose the greatest one as the value of hold(i) to get the greater potential profit: hold(i) = max(a,b,c) Because max(b, c) = max(cash(i-1), hold(i-1) + prices[i] - fee) - prices[i] = cash(i) - prices[i], so hold(i) = max(hold(i-1), cash(i) - prices[i]); There is another way to calculate hold(i), which is more straight forward: You might be holding the stock at the end of day(i-1), and do nothing in day(i): a = hold(i-1); or You might be not holding the stock at the end of day(i-1), and buy it at the end of day(i): b = cash(i-1) - prices[i]; or You might be holding the stock at the end of day(i-1), sell it on day(i), and buy it again at the end of day(i): c = (hold(i-1) + prices[i] - fee) - prices[i] = hold(i-1) - fee; Obviously, a > c, so max(a, c) = a, hold(i) = max(a, b, c) = max(a, b) = max(hold(i-1), cash(i-1) - prices[i]) The target is to find the maximum profit at the end of day(N): cash(
#coding:utf-8 """ 1000. Best Time to Buy and Sell Stock with Transaction Fee Given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee. (You need to pay fee only on selling.) You can complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You can not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.) Return the maximum profit you can make. Example Example 1: Input: prices = [1, 3, 2, 8, 4, 9], fee = 2 Output: 8 Explanation: The maximum profit can be achieved by: Buying at prices[0] = 1 Selling at prices[3] = 8 Buying at prices[4] = 4 Selling at prices[5] = 9 The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8. Example 2: Input: prices = [1, 4, 6, 2, 8, 3, 10, 14], fee = 3 Output: 13 Notice 0 < prices.length <= 50000. 0 < prices[i] < 50000. 0 <= fee < 50000. """ """ 思路:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/solution/ I added some notes below to help me understand it: Only 1 share of the stock can be bought or sold; A stock can be bought or sold for multiple times in one day, but it has to be sold before being bought again; The service fee is only charged when stock is sold; Cash(i): the cash in hand, if you are not holding the stock at the end of day(i): You might be not holding the stock at the end of day(i-1), and do nothing in day(i): a = cash(i-1); or You might be holding the stock at the end of day(i-1), and sell it at the end of day(i): b = hold(i-1) + prices[i] - fee; Choose the greatest one as the value of cash(i) to get the greater potential profit: cash(i) = max(a, b) = max(cash(i-1), hold(i-1) + prices[i] - fee); Hold(i): the cash in hand, if you are holding the stock at the end of day(i): You might be holding the stock at the end of day(i-1), and do nothing in day(i): a = hold(i-1); or You might be not holding the stock at the end of day(i-1), and buy it at the end of day(i): b = cash(i-1) - prices[i]; or You might be holding the stock at the end of day(i-1), sell it on day(i), and buy it again at the end of day(i): c = (hold(i-1) + prices[i] - fee) - prices[i]; Choose the greatest one as the value of hold(i) to get the greater potential profit: hold(i) = max(a,b,c) Because max(b, c) = max(cash(i-1), hold(i-1) + prices[i] - fee) - prices[i] = cash(i) - prices[i], so hold(i) = max(hold(i-1), cash(i) - prices[i]); There is another way to calculate hold(i), which is more straight forward: You might be holding the stock at the end of day(i-1), and do nothing in day(i): a = hold(i-1); or You might be not holding the stock at the end of day(i-1), and buy it at the end of day(i): b = cash(i-1) - prices[i]; or You might be holding the stock at the end of day(i-1), sell it on day(i), and buy it again at the end of day(i): c = (hold(i-1) + prices[i] - fee) - prices[i] = hold(i-1) - fee; Obviously, a > c, so max(a, c) = a, hold(i) = max(a, b, c) = max(a, b) = max(hold(i-1), cash(i-1) - prices[i]) The target is to find the maximum profit at the end of day(N): cash(N); """ class Solution: """ @param prices: a list of integers @param fee: a integer @return: return a integer """ def maxProfit(self, prices, fee): # write your code here size = len(prices) if size<=1: return 0 cash = 0 hold = -prices[0] for i in range(1, size): cash = max(cash, hold+prices[i]-fee) hold = max(hold, cash-prices[i]) return cash
参考:
https://blog.csdn.net/qq_31552435/article/details/52247817
https://blog.csdn.net/linhuanmars/article/details/23236995
https://blog.csdn.net/qq_38702697/article/details/82762654
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/solution/
House Robber
https://www.lintcode.com/problem/house-robber/description
#coding:utf-8 """ 392. House Robber You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. Example Example 1: Input: [3, 8, 4] Output: 8 Explanation: Just rob the second house. Example 2: Input: [5, 2, 1, 3] Output: 8 Explanation: Rob the first and the last house. Challenge O(n) time and O(1) memory. """ class Solution: """ @param A: An array of non-negative integers @return: The maximum amount of money you can rob tonight """ def houseRobber(self, A): # write your code here if len(A)==0: return 0 size = len(A) max_money = [0]*size max_money[0] = A[0] for i in range(1, size): if i==1: max_money[i] = max(max_money[i-1], A[1]) else: max_money[i] = max(max_money[i-2]+A[i], max_money[i-1]) return max_money[-1] #O(1) memory class Solution: """ @param A: An array of non-negative integers @return: The maximum amount of money you can rob tonight """ def houseRobber(self, A): # write your code here if len(A)==0: return 0 size = len(A) if size==1: return A[0] if size== 2: return max(A[0], A[1]) dp_2 = A[0] for i in range(1, size): if i==1: dp_1 = max(dp_2, A[1]) else: dp = max(dp_2+A[i], dp_1) dp_2 = dp_1 dp_1 = dp return dp
https://www.lintcode.com/problem/house-robber-ii/description
#coding:utf-8 """ 534. House Robber II (题目含义参见:https://www.lintcode.com/problem/house-robber/description) After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street. Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. Example Example1 Input: nums = [3,6,4] Output: 6 Example2 Input: nums = [2,3,2,3] Output: 6 Notice This is an extension of House Robber. """ class Solution: """ @param nums: An array of non-negative integers. @return: The maximum amount of money you can rob tonight """ def houseRobber2(self, nums): # write your code here size = len(nums) if size==0: return 0 if size==1: return nums[0] if size==2: return max(nums[0], nums[1]) ret1 =[0]*size ret2 = [0]*(size-1) ret1[0], ret1[1] = 0, nums[1] ret2[0], ret2[1] = nums[0], max(nums[0], nums[1]) for i in range(2, size): if i<size-1: ret2[i] = max(ret2[i-2]+nums[i], ret2[i-1]) ret1[i] = max(ret1[i-2]+nums[i], ret1[i-1]) return max(ret1[-1], ret2[-1])
https://www.lintcode.com/problem/house-robber-iii/description
#coding:utf-8 """ 535. House Robber III The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night. Determine the maximum amount of money the thief can rob tonight without alerting the police. Example Example1 Input: {3,2,3,#,3,#,1} Output: 7 Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7. 3 / \ 2 3 \ \ 3 1 Example2 Input: {3,4,5,1,3,#,1} Output: 9 Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9. 3 / \ 4 5 / \ \ 1 3 1 Notice This problem is the extention of House Robber and House Robber II {3,2,3,#,3,#,1} """ #思路:递归调用每一个根节点,分为取根节点,和取左右节点两种情况 #参考:https://www.jiuzhang.com/solutions/house-robber-iii/#tag-highlight-lang-python """ Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None """ class Solution: """ @param root: The root of binary tree. @return: The maximum amount of money you can rob tonight """ def houseRobber3(self, root): # write your code here rob, not_rob = self.helper(root) return max(rob, not_rob) def helper(self, root): if root == None: return (0, 0) left_rob, left_not_rob = self.helper(root.left) right_rob, right_not_rob = self.helper(root.right) root_rob = root.val + left_not_rob + right_not_rob root_not_rob = max(left_rob, left_not_rob) + max(right_rob, right_not_rob) return root_rob, root_not_rob
Permutation index
https://www.lintcode.com/problem/permutation-index/description
#coding:utf-8 """ 197. Permutation Index Given a permutation which contains no repeated number, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1. Example Example 1: Input:[1,2,4] Output:1 Example 2: Input:[3,2,1] Output:6 """ #思路: #https://blog.csdn.net/Marvin_Huoshan/article/details/80540917 # 为了更加直观的看清楚我们选择一个大点的数组[6,8,4,7,5,3,2]这个数组,他的第一排序是[2,3,4,5,6,7,8]对吧, # 然后首先拿到待计算排序的第一个元素6,那么在6之前比他小的元素有几个呢? 是不是有2,3,4,5这4个, # 确定了第一个元素后,其他剩下的7-1=6个元素进行全排列,共有6!=720种,所以一共有4*(7-1)!种。 # 但是计算第二个元素的时候要小心了。现在第2个元素是8,比8小的元素有几个呢,6个。错!!!, # 因为第一个元素已经确定了,所以应该是还有5个,那么此时剩下的元素进行全排列就有5*(7-2)!种 # 下面是每一位上元素的所有排列情况 # 6 –> 4x(7-1)!种 # 8 –> 5x(7-2)!种 # 4 –> 2x(7-3)!种 # 7 –> 3x(7-4)!种 # 5 –> 2x(7-5)!种 # 3 –> 1x(7-6)!种 # 2 –> 0x(7-7)!种 # 最后再加上一个第1排序 class Solution: """ @param A: An array of integers @return: A long integer """ def permutationIndex(self, A): # write your code here size = len(A) if size==0: return None index = 1 fac = 1 for i in range(size-1, -1, -1): count = 0 for j in range(i+1, size): if A[j]<A[i]: count += 1 #比自己小的数字个数 index += (count*fac) fac *= (size-i) #阶乘累乘 return index
https://www.lintcode.com/problem/permutation-index-ii/description
#coding:utf-8 """ 198. Permutation Index II Given a permutation which may contain repeated numbers, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1. Example Example 1: Input :[1,4,2,2] Output:3 Example 2: Input :[1,6,5,3,1] Output:24 """ #思路:和Permutation IndexI思想一样,只是这道题有重复元素,有无重复元素最大的区别在于原来的1!, 2!, 3!...等需要除以重复元素个数的阶乘。 #134353 (对于这6个数的全排列,3出现了三次,三个位置处的3可以随意排列,而三个3的排列共有3*2*1总,故会重复6次) class Solution: """ @param A: An array of integers @return: A long integer """ def permutationIndexII(self, A): # write your code here size = len(A) if size==0: return 1 frac, ret, frac_rep = 1, 1, 1 repeated_dict = {} for i in range(size-1, -1, -1): if A[i] not in repeated_dict: repeated_dict[A[i]] = 0 repeated_dict[A[i]] += 1 if repeated_dict[A[i]]>1: frac_rep *= repeated_dict[A[i]] counter = 0 for j in range(i+1, size): if A[i]>A[j]: counter += 1 ret += (counter*frac//frac_rep) frac *= (size-i) return ret
Combination Sum
https://www.lintcode.com/problem/combination-sum/description
#coding:utf-8 """ 135. Combination Sum Description Given a set of candidtate numbers candidates and a target number target. Find all unique combinations in candidates where the numbers sums to target. The same repeated number may be chosen from candidates unlimited number of times. All numbers (including target) will be positive integers. Numbers in a combination a1, a2, … , ak must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak) Different combinations can be in any order. The solution set must not contain duplicate combinations. Example 1: Input: candidates = [2, 3, 6, 7], target = 7 Output: [[7], [2, 2, 3]] Example 2: Input: candidates = [1], target = 3 Output: [[1, 1, 1]] """ #参考:https://leetcode-cn.com/problems/combination-sum/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/ class Solution: """ @param candidates: A list of integers @param target: An integer @return: A list of lists of integers """ def combinationSum(self, candidates, target): # write your code here size = len(candidates) if size==0: return [] candidates.sort() #排序保证最后数组按序排列 ret=[] self.dfs(candidates,0,size,target,ret) return ret def dfs(self,candidates,begin,size,target,ret,temp=[]): if target==0: if temp not in ret: ret.append(temp[:]) return if target<0: return for i in range(begin,size): temp.append(candidates[i]) self.dfs(candidates,i,size,target-candidates[i],ret,temp) #从i开始往后选下一个数据,保证避免出现重复 temp.pop()
https://www.lintcode.com/problem/combination-sum-ii/description
#coding:utf-8 """ 153. Combination Sum II Description Given an array num and a number target. Find all unique combinations in num where the numbers sum to target. Each number in num can only be used once in one combination. All numbers (including target) will be positive integers. Numbers in a combination a1, a2, … , ak must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak) Different combinations can be in any order. The solution set must not contain duplicate combinations. Example 1: Input: num = [7,1,2,5,1,6,10], target = 8 Output: [[1,1,6],[1,2,5],[1,7],[2,6]] Example 2: Input: num = [1,1,1], target = 2 Output: [[1,1]] Explanation: The solution set must not contain duplicate combinations. """ class Solution: """ @param num: Given the candidate numbers @param target: Given the target number @return: All the combinations that sum to target """ def combinationSum2(self, num, target): # write your code here if len(num)==0: return [] ret=[] self.dfs(num,0,target,ret) return ret def dfs(self,num,i,target,ret,temp=[]): if target==0: sort_temp=sorted(temp) if sort_temp not in ret: ret.append(sort_temp) return if target<0: return if i==len(num): return while i<len(num): temp.append(num[i]) self.dfs(num,i+1,target-num[i],ret,temp) temp.pop() i+=1 if __name__=="__main__": s=Solution() print(s.combinationSum2(num = [7,1,2,5,1,6,10], target = 8)) print(s.combinationSum2(num = [1,1,1], target = 2)) print(s.combinationSum2(num = [2,3,6,7], target = 7))
https://www.lintcode.com/problem/combination-sum-iv/description
#coding:utf-8 """ 564. Combination Sum IV Given an integer array nums with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target. Example Example1 Input: nums = [1, 2, 4], and target = 4 Output: 6 Explanation: The possible combination ways are: [1, 1, 1, 1] [1, 1, 2] [1, 2, 1] [2, 1, 1] [2, 2] [4] Example2 Input: nums = [1, 2], and target = 4 Output: 5 Explanation: The possible combination ways are: [1, 1, 1, 1] [1, 1, 2] [1, 2, 1] [2, 1, 1] [2, 2] Notice A number in the array can be used multiple times in the combination. Different orders are counted as different combinations. """ #动态规划,完全背包问题(0/1 背包) #参考:https://www.jiuzhang.com/solutions/combination-sum-iv/ class Solution: """ @param nums: an integer array and all positive numbers, no duplicates @param target: An integer @return: An integer """ def backPackVI(self, nums, target): # write your code here if len(nums)==0: return 0 dp = [0]*(target+1) dp[0] =1 for i in range(1, target+1): for j in range(0, len(nums)): if i>=nums[j]: dp[i] += dp[i-nums[j]] return dp[target] if __name__ == "__main__": s = Solution() nums = [1,2,4] target = 4 s.backPackVI(nums, target)
Linked list cycle
https://www.lintcode.com/problem/linked-list-cycle/description
#coding:utf-8 """ 102. Linked List Cycle Given a linked list, determine if it has a cycle in it. Example Example 1: Input: 21->10->4->5, then tail connects to node index 1(value 10). Output: true Example 2: Input: 21->10->4->5->null Output: false ``` Challenge Follow up: Can you solve it without using extra space? """ """ Definition of ListNode class ListNode(object): def __init__(self, val, next=None): self.val = val self.next = next """ class Solution: """ @param head: The first node of linked list. @return: True if it has a cycle, or false """ def hasCycle(self, head): # write your code here if not head or not head.next: return False slow = head.next fast = head.next.next while fast and fast.next: if fast == slow: return True fast = fast.next.next slow = slow.next
https://www.lintcode.com/problem/linked-list-cycle-ii/description
#coding:utf-8 """ 103. Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Example Example 1: Input:null,no cycle Output:no cycle Explanation: List is null,so no cycle. Example 2: Input:-21->10->4->5,tail connects to node index 1 Output:10 Explanation: The last node 5 points to the node whose index is 1, which is 10, so the entrance of the ring is 10 Challenge Follow up: Can you solve it without using extra space? """ """ Definition of ListNode class ListNode(object): def __init__(self, val, next=None): self.val = val self.next = next """ class Solution: """ @param head: The first node of linked list. @return: The node where the cycle begins. if there is no cycle, return null """ def detectCycle(self, head): # write your code here if head==None or head.next==None: return None fast = slow = head cycle = False while fast and fast.next and not cycle: fast = fast.next.next slow = slow.next if fast is slow: cycle = True if cycle: fast = head while fast is not slow: fast = fast.next slow = slow.next return fast else: return None
Calculator I
https://www.lintcode.com/problem/basic-calculator/description (Calculator I)
https://www.lintcode.com/problem/basic-calculator-ii/description (Calculator II)
https://www.lintcode.com/problem/basic-calculator-iii/description(Calculator III)
#coding:utf-8 """ 849. Basic Calculator III Implement a basic calculator to evaluate a simple expression string. The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces . The expression string contains only non-negative integers, +, -, *, / operators , open ( and closing parentheses ) and empty spaces . The integer division should truncate toward zero. You may assume that the given expression is always valid. All intermediate results will be in the range of [-2147483648, 2147483647] Example Example 1: Input:"1 + 1" Output:2 Explanation:1 + 1 = 2 Example 2: Input:" 6-4 / 2 " Output:4 Explanation:4/2=2,6-2=4 Notice Do not use the eval built-in library function. """ class Solution: """ @param s: the expression string @return: the answer """ def calculate(self, s): # Write your code here if not s: return None postfix = self.pre_to_post(s) temp = [] for token in postfix: if token in "+-*/": operand2 = temp.pop() operand1 = temp.pop() result = self.do_math(operand1, operand2, token) temp.append(result) else: temp.append(int(token)) return temp.pop() def pre_to_post(self, s): import string digits = string.digits operators = {"(":1,"+":2,"-":2, "*":3, "/":3} stack = [] que = [] size = len(s) multi_digit = "" for i in range(size): if s[i]== " ": continue if s[i]=="(": stack.append(s[i]) elif s[i] in digits: multi_digit += s[i] if i<size-1 and s[i+1] in digits: continue que.append(multi_digit) multi_digit = "" elif s[i] in operators.keys(): while stack and operators[stack[-1]]>=operators[s[i]]: que.append(stack.pop()) stack.append(s[i]) elif s[i]==")": while stack and stack[-1]!="(": que.append(stack.pop()) stack.pop() while stack: que.append(stack.pop()) return que def do_math(self, operand1, operand2, token): if token=='*': return operand1 * operand2 elif token=='/': return operand1 // operand2 elif token=='+': return operand1 + operand2 else: return operand1 - operand2
C9. CV specific problems
Range sum 1d immutuable
https://www.lintcode.com/problem/range-sum-query-immutable/description
#coding:utf-8 """ 943. Range Sum Query - Immutable Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. Example Example1 Input: nums = [-2, 0, 3, -5, 2, -1] sumRange(0, 2) sumRange(2, 5) sumRange(0, 5) Output: 1 -1 -3 Explanation: sumRange(0, 2) -> (-2) + 0 + 3 = 1 sumRange(2, 5) -> 3 + (-5) + 2 + (-1) = -1 sumRange(0, 5) -> (-2) + 0 + 3 + (-5) + 2 + (-1) = -3 Example2 Input: nums = [-4, -5] sumRange(0, 0) sumRange(1, 1) sumRange(0, 1) sumRange(1, 1) sumRange(0, 0) Output: -4 -5 -9 -5 -4 Explanation: sumRange(0, 0) -> -4 sumRange(1, 1) -> -5 sumRange(0, 1) -> (-4) + (-5) = -9 sumRange(1, 1) -> -5 sumRange(0, 0) -> -4 Notice You may assume that the array does not change. There are many calls to sumRange function. """ #思路:积分图 class NumArray(object): def __init__(self, nums): """ :type nums: List[int] """ size = len(nums) self.nums = nums if size>0: self.range_sum=[0]*(size+1) for i in range(1, size+1): self.range_sum[i] = self.range_sum[i-1]+nums[i-1] def sumRange(self, i, j): """ :type i: int :type j: int :rtype: int """ return self.range_sum[j+1]-self.range_sum[i] # Your NumArray object will be instantiated and called as such: # obj = NumArray(nums) # param_1 = obj.sumRange(i,j)
Range sum 1d mutuable
https://www.lintcode.com/problem/range-sum-query-mutable/description
#coding:utf-8 """ 840. Range Sum Query - Mutable Given an integer array nums, and then you need to implement two functions: update(i, val) Modify the element whose index is i to val. sumRange(l, r) Return the sum of elements whose indexes are in range of [l,r][l, r][l,r]. Example Example 1: Input: nums = [1, 3, 5] sumRange(0, 2) update(1, 2) sumRange(0, 2) Output: 9 8 Example 2: Input: nums = [0, 9, 5, 7, 3] sumRange(4, 4) sumRange(2, 4) update(4, 5) update(1, 7) update(0, 8) sumRange(1, 2) Output: 3 15 12 Notice The array is only modifiable by the update function. You may assume the number of calls to update and sumRange function is distributed evenly. """ #思路:分段树 #参考:https://leetcode.com/problems/range-sum-query-mutable/solution/ class NumArray: def __init__(self, nums): """ :type nums: List[int] """ self.size = len(nums) if self.size>0: self.tree = [0]*(2*self.size) for i in range(self.size, 2*self.size): self.tree[i] = nums[i-self.size] for j in range(self.size-1, 0, -1): #注意tree[0]为多出来的空元素,因为i=0时,2*i也为0 self.tree[j] = self.tree[2*j] + self.tree[2*j+1] def update(self, i, val): """ :type i: int :type val: int :rtype: void """ i+=self.size self.tree[i] = val while i>0: left, right = i, i if i&1: left = i -1 else: right = i + 1 self.tree[i//2] = self.tree[left] + self.tree[right] i = i//2 def sumRange(self, i, j): """ :type i: int :type j: int :rtype: int """ i += self.size j += self.size sum=0 while i<=j: if i&1: sum += self.tree[i] i += 1 if not j&1: sum += self.tree[j] j -= 1 i = i//2 j = j//2 return sum # Your NumArray object will be instantiated and called as such: # obj = NumArray(nums) # obj.update(i,val) # param_2 = obj.sumRange(i,j)
Range sum 2d immutable
https://www.lintcode.com/problem/range-sum-query-2d-immutable/description
#coding:utf-8 """ 665. Range Sum Query 2D - Immutable Given a 2D matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). Example Example1 Input: [[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]] sumRegion(2, 1, 4, 3) sumRegion(1, 1, 2, 2) sumRegion(1, 2, 2, 4) Output: 8 11 12 Explanation: Given matrix = [ [3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5] ] sumRegion(2, 1, 4, 3) = 2 + 0 + 1 + 1 + 0 + 1 + 0 + 3 + 0 = 8 sumRegion(1, 1, 2, 2) = 6 + 3 + 2 + 0 = 11 sumRegion(1, 2, 2, 4) = 3 + 2 + 1 + 0 + 1 + 5 = 12 Example2 Input: [[3,0],[5,6]] sumRegion(0, 0, 0, 1) sumRegion(0, 0, 1, 1) Output: 3 14 Explanation: Given matrix = [ [3, 0], [5, 6] ] sumRegion(0, 0, 0, 1) = 3 + 0 = 3 sumRegion(0, 0, 1, 1) = 3 + 0 + 5 + 6 = 14 Notice You may assume that the matrix does not change. There are many calls to sumRegion function. You may assume that row1 ≤ row2 and col1 ≤ col2. [[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]] sumRegion(2, 1, 4, 3) sumRegion(1, 1, 2, 2) sumRegion(1, 2, 2, 4) """ #积分图 class NumMatrix: """ @param: matrix: a 2D matrix """ def __init__(self, matrix): # do intialization if necessary if len(matrix) and len(matrix[0]): rows, cols = len(matrix), len(matrix[0]) self.matrix = matrix self.col_sum = [0]*cols self.range_sum = [[0]*(cols+1) for i in range(rows+1)] for i in range(1, rows+1): for j in range(1, cols+1): self.range_sum[i][j] = self.matrix[i-1][j-1]-self.range_sum[i-1][j-1]+self.range_sum[i][j-1]+self.range_sum[i-1][j] """ @param: row1: An integer @param: col1: An integer @param: row2: An integer @param: col2: An integer @return: An integer """ def sumRegion(self, row1, col1, row2, col2): # write your code here area = self.range_sum[row2+1][col2+1]-self.range_sum[row2+1][col1]-self.range_sum[row1][col2+1]+self.range_sum[row1][col1] return area # Your NumMatrix object will be instantiated and called as such: # obj = NumMatrix(matrix) # param_1 = obj.sumRegion(row1,col1,row2,col2)
Range sum 2d immutable
https://www.lintcode.com/problem/range-sum-query-2d-mutable/description
Sliding window Maximum
https://www.lintcode.com/problem/sliding-window-maximum/description
#coding:utf-8 """ 362. Sliding Window Maximum Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration from the start of the array, find the maximum number inside the window at each moving. Example Example 1: Input: [1,2,7,7,8] 3 输出: [7,7,8] Explanation: At first the window is at the start of the array like this `[|1, 2, 7| ,7, 8]` , return the maximum `7`; then the window move one step forward.`[1, |2, 7 ,7|, 8]`, return the maximum `7`; then the window move one step forward again.`[1, 2, |7, 7, 8|]`, return the maximum `8`; Example 2: Input: [1,2,3,1,2,3] 5 Output: [3,3] Explanation: At first, the state of the window is as follows: ` [,2,3,1,2,1 | , 3] `, a maximum of ` 3 `; And then the window to the right one. ` [1, | 2,3,1,2,3 |] `, a maximum of ` 3 `; Challenge o(n) time and O(k) memory """ #双端队列,队列的最左端总是保存窗口中最大值的index class Solution: """ @param nums: A list of integers. @param k: An integer @return: The maximum number inside the window at each moving. """ def maxSlidingWindow(self, nums, k): # write your code here size = len(nums) if not size: return [] index, res = [], [] for i in range(0, k): while index and nums[i]>=nums[index[-1]]: index.pop() index.append(i) for j in range(k, size): res.append(nums[index[0]]) while index and nums[j]>=nums[index[-1]]: index.pop() while index and index[0]<=j-k: #保证队列最左端保存的是窗口[j-k+1, j]中的index index.pop(0) index.append(j) res.append(nums[index[0]]) return res
Convolution: Medain Filter
#coding:utf-8 import heapq import cv2 #实现图片的中值滤波算法 # 2D median filter with no stride, zero padding def medain_filter(img, kernel_w, kernel_h): """ img: cv2 matrix kernel_w: kernel width kernel_h: kernel height """ rows, cols = img.shape[:2] for i in range(rows): for j in range(cols): left = max(0, j-kernel_w//2) right = min(cols-1, j+kernel_w//2) upper = max(0, i-kernel_h//2) lower = min(rows-1, i+kernel_h//2) #kernel中的像素点放入堆中 hq = [] for m in range(upper, lower+1): for n in range(left, right+1): heapq.heappush(hq, img[m][n]) size = (right-left+1)*(lower-upper+1) if size&1: #奇数个元素,取中间值 for k in range(0, (size+1)//2): median = heapq.heappop(hq) img[i][j] = median else: #偶数个元素,取中间两个元素平均值 for k in range(0, (size+1)//2): median1 = heapq.heappop(hq) median2 = heapq.heappop(hq) img[i][j] = (median1+median2)//2 return img if __name__ == "__main__": img = cv2.imread(r"C:\Users\Administrator\Desktop\dog.jpg", 0) img2 = medain_filter(img, 3, 3) cv2.imshow("img", img) cv2.imshow("img2", img2) cv2.waitKey(0) cv2.destroyAllWindows()
Convolution: Average Pooling
#coding:utf-8 import cv2 #平均池化算法实现 #Average Pooling with zero padding, stride def average_pooling(img, kernel_w, kernel_h, stride=1): """ img: cv2 matrix kernel_w: kernel width kernel_h: kernel height stride: sliding length """ rows, cols, channel = img.shape[:] for i in range(channel): for j in range(0, rows, stride): for k in range(0, cols, stride): left = max(0, j-kernel_w//2) right = min(cols-1, j+kernel_w//2) upper = max(0, i-kernel_h//2) lower = min(rows-1, i+kernel_h//2) #计算平均值 area = (right-left+1)*(lower-upper+1) sum = 0 for m in range(upper, lower+1): for n in range(left, right+1): sum += img[m, n, i] img[j, k, i] = sum//area return img if __name__ == "__main__": img = cv2.imread(r"C:\Users\Administrator\Desktop\dog.jpg") img2 = average_pooling(img, 3, 3, 1) cv2.imshow("img", img) cv2.imshow("img2", img2) cv2.waitKey(0) cv2.destroyAllWindows()
D Classic Question
Hannoi
Champagne Tower
https://www.lintcode.com/problem/champagne-tower/description
#coding:utf-8 """ 1018. Champagne Tower We stack glasses in a pyramid, where the first row has 1 glass, the second row has 2 glasses, the third row has 3 glasses and so on until the 100th row. Each glass holds one cup (250ml) of champagne. Then, some champagne is poured in the first glass at the top. When the top most glass is full, any excess liquid poured will fall equally to the glass immediately to the left and right of it. When those glasses become full, any excess champagne will fall equally to the left and right of those glasses, and so on. (A glass at the bottom row has it's excess champagne fall on the floor.) For example, after one cup of champagne is poured, the top most glass is full. After two cups of champagne are poured, the two glasses on the second row are half full. After three cups of champagne are poured, those two cups become full - there are 3 full glasses total now. After four cups of champagne are poured, the third row has the middle glass half full, and the two outside glasses are a quarter full, as pictured below. Now after pouring some non-negative integer cups of champagne, return how full the j-th glass in the i-th row is (both i and j are 0 indexed). Example Example 1: Input: poured = 1, query_glass = 1, query_row = 1 Output: 0.0 Explanation: We poured 1 cup of champange to the top glass of the tower (which is indexed as (0, 0)). There will be no excess liquid so all the glasses under the top glass will remain empty. Example 2: Input: poured = 2, query_glass = 1, query_row = 1 Output: 0.5 Explanation: We poured 2 cups of champange to the top glass of the tower (which is indexed as (0, 0)). There is one cup of excess liquid. The glass indexed as (1, 0) and the glass indexed as (1, 1) will share the excess liquid equally, and each will get half cup of champange. Notice poured will be in the range of [0, 10 ^ 9]. query_glass and query_row will be in the range of [0, 99]. """ #思路:动态规划,参考https://blog.csdn.net/qq_23523409/article/details/85540095 #dp[i][j] 第i层,第j杯的香槟总数 # 先将总数为sum的香槟放入最顶上的杯子,也就是数组下标为[0][0]的地方香槟总数为sum。假设dp[i][j]为数组下标为[i][j]获得的香槟总数,dp[0][0]=sum。 # 除dp[0][0]以外,所有值均为0. # 如果sum>1,那么剩余的香槟必然溢出到下一层的[i+1][j]和[i+1][j+1]两个位置。 # 根据题意,等流量的条件,dp[i+1][j]+=(dp[i][j]-1)*0.5,dp[i+1][j+1]+=(dp[i][j]-1)*0.5。 # 迭代100次必然可以算出所有杯子的状态。(实际只需迭代到需要查询的层数) class Solution: """ @param poured: an integer @param query_row: an integer @param query_glass: an integer @return: return a double """ def champagneTower(self, poured, query_row, query_glass): # write your code here if poured==0: return 0.0 dp = [[0.0]*(query_row+1) for i in range(query_row+1)] dp[0][0] = poured for i in range(1, query_row+1): for j in range(query_row+1): if dp[i-1][j-1]>1: #上一层会溢出到下一层的左右两个杯子 dp[i][j-1] += (dp[i-1][j-1] -1)/2 dp[i][j] += (dp[i-1][j-1]-1)/2 if dp[query_row][query_glass]>1: #大于1表示装满了,会溢出到下一层,此杯状态即为1 return 1.0 else: return dp[query_row][query_glass]
N-Queens
https://www.lintcode.com/problem/n-queens/description
#coding:utf-8 """ 33. N-Queens Description The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively. Example 1: Input:1 Output: [["Q"]] Example 2: Input:4 Output: [ // Solution 1 [".Q..", "...Q", "Q...", "..Q." ], // Solution 2 ["..Q.", "Q...", "...Q", ".Q.." ] ] """ class Solution: """ @param: n: The number of queens @return: All distinct solutions """ def solveNQueens(self, n): # write your code here if n==0: return 0 ret=[] self.dfs(n, 0, ret) return ret def dfs(self, n, index, ret, temp=[]): if index==n: m = self.tomap(n, temp) ret.append(m) s=[] for i in range(index): s.append(temp[i]+(index-i)) s.append(temp[i]-(index-i)) for i in range(n): if i not in (s+temp): temp.append(i) self.dfs(n,index+1,ret,temp) temp.pop() def tomap(self, n, temp): m=[] for i in temp: line = "."*i+"Q"+"."*(n-i-1) m.append(line) return m
N-Queens
https://www.lintcode.com/problem/n-queens-ii/description
#coding:utf-8 """ Description 34. N-Queens II Follow up for N-Queens problem. (即任意两个皇后都不能处于同一行、同一列或同一斜线上) Now, instead outputting board configurations, return the total number of distinct solutions. Example 1: Input: n=1 Output: 1 Explanation: 1: 1 Example 2: Input: n=4 Output: 2 Explanation: 1: 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 2: 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 """ class Solution: """ @param n: The number of queens. @return: The total number of distinct solutions. """ def totalNQueens(self, n): # write your code here if n==0: return 0 self.num=0 self.dfs(n,0) return self.num def dfs(self, n, index, ret=[]): if index==n: self.num+=1 return temp=[] for i in range(index): temp.append(ret[i]+(index-i)) temp.append(ret[i]-(index-i)) for i in range(n): if i not in (temp+ret): ret.append(i) self.dfs(n,index+1,ret) ret.pop()
Minesweeper
https://www.lintcode.com/problem/minesweeper/description
#coding:utf-8 """ 1189. 扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵。 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字('1' 到 '8')表示有多少地雷与这块已挖出的方块相邻,'X' 则表示一个已挖出的地雷。 现在给出在所有未挖出的方块中('M'或者'E')的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板: 如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X'。 如果一个没有相邻地雷的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的方块都应该被递归地揭露。 如果一个至少与一个地雷相邻的空方块('E')被挖出,修改它为数字('1'到'8'),表示相邻地雷的数量。 如果在此次点击中,若无更多方块可被揭露,则返回面板。 Example 样例 1: 输入: board = ["EEEEE","EEMEE","EEEEE","EEEEE"], Click : [3,0] 输出: ["B1E1B","B1M1B","B111B","BBBBB"] 样例 2: 输入: board = ["B1E1B","B1M1B", "B111B","BBBBB"], Click : [1,2] 输出: ["B1E1B","B1X1B","B111B","BBBBB"] Notice 1.输入矩阵的宽和高的范围为 [1,50]。 2.点击的位置只能是未被挖出的方块 ('M' 或者 'E'),这也意味着面板至少包含一个可点击的方块。 3.输入面板不会是游戏结束的状态(即有地雷已被挖出)。 4.简单起见,未提及的规则在这个问题中可被忽略。例如,当游戏结束时你不需要挖出所有地雷,考虑所有你可能赢得游戏或标记方块的情况。 """ """ 题目意思:矩阵都是M和E,碰到M改为X,返回M;碰到E,周边有雷时,改为雷的数量,不用遍历其附件点;周边无雷时,改为“B”,继续遍历其周围的八个点 """ class Solution: """ @param board: a board @param click: the position @return: the new board """ def updateBoard(self, board, click): # Write your code here if not len(board) and not len(board[0]): return board board = [list(item) for item in board] direction = [[1, 0], [1, -1], [1, 1], [0, 1],[-1, 0], [-1, -1], [-1, 1], [0, -1]] self.dfs(board, click, direction) return ["".join(item) for item in board] def dfs(self, board, click, direction): if not self.is_valid(board, click[0], click[1]): return if board[click[0]][click[1]]=="M": board[click[0]][click[1]]="X" return elif board[click[0]][click[1]]=="E": count = self.count_mine(board, click, direction) if count: board[click[0]][click[1]]=str(count) else: board[click[0]][click[1]]="B" for step in direction: r = click[0] + step[0] c = click[1] + step[1] self.dfs(board, [r,c], direction) def is_valid(self, board, x, y): rows, cols = len(board), len(board[0]) return 0<=x<rows and 0<=y<cols def count_mine(self,board, cur, direction): count = 0 for step in direction: r = cur[0] + step[0] c = cur[1] + step[1] if self.is_valid(board, r, c): if board[r][c]=="M": count+=1 return count if __name__=="__main__": s = Solution() board = ["EEEEE","EEMEE","EEEEE","EEEEE"] Click =[3,0] print(s.updateBoard(board, Click))
24 Game
https://www.lintcode.com/problem/24-game/description
#coding:utf-8 """ 739. 24 Game You have 4 cards each containing a number from 1 to 9. You need to compute whether they could operated through *, /, +, -, (, ) to get the value of 24. Example Example 1: Input:[1, 4, 8, 7] Output:true Explanation:8 * (7 - 4) * 1 = 24 Example 2: Input:[1, 1, 1, 2] Output:false Explanation:no way to get 24 Example 3: Input:[3, 3, 8, 8] Output:true Explanation:8 / ( 3 - 8 / 3) = 24 Notice The division operator / represents real division, not integer division. so 4 / (1 - 2/3) = 12. Every operation done is between two numbers. In particular, we cannot use - as a unary operator. For example, with [1, 1, 1, 1] as input, the expression -1 - 1 - 1 - 1 is not allowed. You cannot concatenate numbers together. For example, if the input is [1, 2, 1, 2], we cannot write this as 12 + 12. """ #参考:https://leetcode-cn.com/problems/24-game/solution/24dian-you-xi-by-leetcode/ #递归: class Solution: """ @param nums: 4 cards @return: whether they could get the value of 24 """ def compute24(self, nums): # write your code here from operator import add, mul, truediv, sub if not nums: return False if len(nums)==1: return abs(nums[0]-24) < 1e-6 for i in range(len(nums)): for j in range(len(nums)): if i!=j: B = [nums[k] for k in range(len(nums)) if k!=i and k!=j] for op in [add, mul, truediv, sub]: if (op is add or op is mul) and j>i: continue if op is not truediv or nums[j]: B.append(op(nums[i], nums[j])) if self.compute24(B): return True B.pop() return False #遍历 class Solution: """ @param nums: 4 cards @return: whether they could get the value of 24 """ def compute24(self, nums): # write your code here def cal(a,b): if a == 0: return b,-b,0 if b == 0: return a,-a,0 return list({a+b,a-b,b-a,a*b,a/b,b/a}) stack = [[float(item) for item in nums]] while (len(stack) > 0): tmp_nums = stack.pop() if len(tmp_nums) == 1: if abs(tmp_nums[0] - 24.0) <= 0.0001: return True continue l = len(tmp_nums) for n1 in range(l - 1): for n2 in range(n1 + 1,l): tmp_cals = cal(tmp_nums[n1],tmp_nums[n2]) for tmp_cal in tmp_cals: tmp_res = [tmp_cal] + tmp_nums[:n1] + tmp_nums[n1 + 1:n2] + tmp_nums[n2 + 1:] stack.append(tmp_res) return False
E. Bit Operations
Single Number
https://www.lintcode.com/problem/single-number/description
#coding:utf-8 """ 82. Single Number Given 2 * n + 1 numbers, every numbers occurs twice except one, find it. Example Example 1: Input:[1,1,2,2,3,4,4] Output:3 Explanation: Only 3 appears once Example 2: Input:[0,0,1] Output:1 Explanation: Only 1 appears once Challenge One-pass, constant extra space. Notice n≤100 """ #异或运算,相同的数字异或运算后为0 class Solution: """ @param A: An integer array @return: An integer """ def singleNumber(self, A): # write your code here if not len(A): return None size = len(A) ret = A[0] for i in range(1, size): ret = ret^A[i] return ret
Single Number II
https://www.lintcode.com/problem/single-number-ii/description
#coding:utf-8 """ 83. Single Number II Given 3*n + 1 non-negative integer, every numbers occurs triple times except one, find it. Example Example 1: Input: [1,1,2,3,3,3,2,2,4,1] Output: 4 Example 2: Input: [2,1,2,2] Output: 1 Challenge One-pass, constant extra space. """ #思路:三个相同的数相加,不仅其和能被3整除,其二进制位上的每一位也能被3整除(若不考虑进位),以3为例,若使用不进位加法,三个3相加的结果为:0011+0011+0011=0033 #因此利用位运算,int有32位,用一个长度为32的数组记录每个数字的所有位中1出现的次数,如果这个数字出现3次,则与这个数字对应的每一位上的1也出现三次。最后将数组每一位均对3取余,最后得到的就是要求的数字。 class Solution: """ @param A: An integer array @return: An integer """ def singleNumberII(self, A): # write your code here if not len(A): return None size = len(A) ret = 0 bits = [0]*32 for i in range(32): for j in range(size): bits[i] = bits[i] + ((A[j]>>i) & 1) #i位上比特为1的数字个数 bits[i] = bits[i]%3 #i位上比特为1的数字若出现三次的倍数,则余数为0 ret = ret | (bits[i]<<i) return ret
Single Number III
https://www.lintcode.com/problem/single-number-iii/description
#coding:utf-8 """ 84. Single Number III Given 2*n + 2 numbers, every numbers occurs twice except two, find them. Example Example 1: Input: [1,2,2,3,4,4,5,3] Output: [1,5] Example 2: Input: [1,1,2,3,4,4] Output: [2,3] Challenge O(n) time, O(1) extra space. """ #思路:对2*n + 2数字进行异或,相同的数字异或为0,假设最后两个只出现一次的数分别为x1, x2,那么异或最后的结果为x1 ^ x2,可以根据x1 ^ x2 ^ x1 = x2求得x2, 同理可得x_1 #那么问题是如何找到x1, x2, 有点死循环了? #由于x1, x2不相等,那么其异或结果肯定有一个比特位为1,假设为k位,那么可以根据第k位是否为1,将2*n + 2个数字分成两组; #对于这两组,一组肯定包含x1,组内其他数字肯定两两相同,组内全部异或即得到x1; 另一组同理可得x2 class Solution: """ @param A: An integer array @return: An integer array """ def singleNumberIII(self, A): # write your code here if not len(A): return None size = len(A) ans = A[0] for i in range(1, size): ans = ans^A[i] k = 0 ans1, ans2 =ans, ans while not ans&1: k+=1 ans >>= 1 for i in range(0, size): kbit = ((A[i]>>k) & 1) if kbit: ans1 ^= A[i] else: ans2 ^= A[i] return [ans1, ans2]
Single Number IV
https://www.lintcode.com/problem/single-number-iv/description
#coding:utf-8 """ 824. Single Number IV Give an array, all the numbers appear twice except one number which appears once and all the numbers which appear twice are next to each other. Find the number which appears once. Example Example 1: Input: [3,3,2,2,4,5,5] Output: 4 Explanation: 4 appears only once. Example 2: Input: [2,1,1,3,3] Output: 2 Explanation: 2 appears only once. """ #注意末尾元素 class Solution: """ @param nums: The number array @return: Return the single number """ def getSingleNumber(self, nums): # Write your code here if not len(nums): return None for i in range(0, len(nums)-1, 2): if nums[i]!=nums[i+1]: return nums[i] return nums[-1]
Hamming Distance
https://www.lintcode.com/problem/hamming-distance/description
#coding:utf-8 """ 835. Hamming Distance The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Given two integers x and y, calculate the Hamming distance. Example Example1 Input: x = 1 and y = 4 Output: 2 Explanation: The binary representation of 1 is 001 The binary representation of 4 is 100 There are 2 different bits Example2 Input: x = 5 and y = 2 Output: 3 Explanation: The binary representation of 5 is 101 The binary representation of 2 is 010 There are 3 different bits Notice 0 ≤ x, y < 231 """ #异或运算,不同的bit位为1 class Solution: """ @param x: an integer @param y: an integer @return: return an integer, denote the Hamming Distance between two integers """ def hammingDistance(self, x, y): # write your code here ans = x^y i = 0 while ans: if ans&1: i += 1 ans >>= 1 return i
Total Hamming Distance
https://www.lintcode.com/problem/total-hamming-distance/description
class Solution: """ @param nums: the gievn integers @return: the total Hamming distance between all pairs of the given numbers """ def totalHammingDistance(self, nums): # Write your code here if not len(nums): return 0 size = len(nums) bits = [0]*32 ret = 0 for i in range(32): for j in range(size): bits[i] += ((nums[j]>>i) & 1) ret += bits[i]*(size-bits[i]) return ret
F.动态规划
Longest Common Subsequence
https://www.lintcode.com/problem/longest-common-subsequence/description
#coding:utf-8 """ 77. Longest Common Subsequence Given two strings, find the longest common subsequence (LCS). Your code should return the length of LCS. Example Example 1: Input: "ABCD" and "EDCA" Output: 1 Explanation: LCS is 'A' or 'D' or 'C' Example 2: Input: "ABCD" and "EACB" Output: 2 Explanation: LCS is "AC" Clarification What's the definition of Longest Common Subsequence? https://en.wikipedia.org/wiki/Longest_common_subsequence_problem http://baike.baidu.com/view/2020307.htm """ #动态规划问题: class Solution: """ @param A: A string @param B: A string @return: The length of longest common subsequence of A and B """ def longestCommonSubsequence(self, A, B): # write your code here if not len(A) or not len(B): return 0 length1, length2 = len(A), len(B) dp = [[0]*(length1+1) for i in range(length2+1)] for i in range(1, length1+1): for j in range(1, length2+1): if A[i-1]==B[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) return dp[length1][length2]
#coding:utf-8 """ F2. 硬币翻转(红绿灯问题): 假设有一组硬币,材质非均匀, 因而它们各自抛出后正面朝上的概率不同,假设为 p1,p2,…,pn 。 问:当依次抛掷共n次后, 出现k次正面朝上的概率是多少 """ def get_coin_prob(prob_list, k): """ prob_list: n块硬币正面朝上的概率 k: n块硬币各抛依次,出现k次正面朝上 """ if not len(prob_list): return 0 n = len(prob_list) dp = [[0]*(k+1) for i in range(n+1)] #dp[i][j] 抛i次出现j次正面朝上的概率 dp[0][0] = 1 for i in range(1, n+1): dp[i][0] = (1-prob_list[i-1])*dp[i-1][0] for i in range(1, n+1): for j in range(k+1): dp[i][j] = dp[i-1][j-1]*prob_list[i-1] + dp[i-1][j]*(1-prob_list[i-1]) return dp[n][k]
G.Trie(字典树)
Word search II
#coding:utf-8 """ lintcode 132. Word Search II Description Given a matrix of lower alphabets and a dictionary. Find all words in the dictionary that can be found in the matrix. A word can start from any position in the matrix and go left/right/up/down to the adjacent position. One character only be used once in one word. No same word in dictionary Example 1: Input:["doaf","agai","dcan"],["dog","dad","dgdg","can","again"] Output:["again","can","dad","dog"] Explanation: d o a f a g a i d c a n search in Matrix,so return ["again","can","dad","dog"]. Example 2: Input:["a"],["b"] Output:[] Explanation: a search in Matrix,return []. Challenge Using trie to implement your algorithm. """ #参考:https://www.jiuzhang.com/solutions/word-search-ii/#tag-highlight-lang-python #构建trie tree class TrieNode(object): def __init__(self): self.children={} self.is_word=False self.word=None class TrieTree(object): def __init__(self): self.root = TrieNode() def add(self,word): node =self.root for c in word: if c not in node.children: node.children[c]=TrieNode() node = node.children[c] node.is_word=True node.word=word def search(self,word): node = self.root for c in word: if c not in node.children: return None node = node.children[c] return node DIRECTIONS=[(0,1),(0,-1),(-1,0),(1,0)] class Solution: """ @param board: A list of lists of character @param words: A list of string @return: A list of string """ def wordSearchII(self, board, words): # write your code here if len(words)==0 or len(board)==0: return [] trie = TrieTree() for word in words: trie.add(word) ret = [] root = trie.root for i in range(len(board)): for j in range(len(board[i])): self.search(board,i,j,root,ret,set([(i,j)])) return ret def search(self,board,i,j,node,ret,visited): node = node.children.get(board[i][j],None) if node==None: return if node.is_word and node.word not in ret: ret.append(node.word) for d in DIRECTIONS: x,y = i+d[0],j+d[1] if self.in_board(x,y,board): if (x,y) not in visited: visited.add((x,y)) self.search(board,x,y,node,ret,visited) visited.remove((x,y)) def in_board(self,x,y,board): if 0<= x <len(board) and 0<=y<len(board[x]): return True #用图的方法,如何避免一个字母不被重复利用? # class Solution: # """ # @param board: A list of lists of character # @param words: A list of string # @return: A list of string # """ # def wordSearchII(self, board, words): # #write your code here # if len(words)==0 or len(board)==0: # return [] # #建立图 # graph = dict() # length1=len(board) # for i in range(length1): # length2 = len(board[i]) # for j in range(length2): # if board[i][j] not in graph: # graph[board[i][j]]=set() # if i>0 and j<len(board[i-1]): # graph[board[i][j]].add(board[i-1][j]) # if i<length1-1 and j<len(board[i+1]): # graph[board[i][j]].add(board[i+1][j]) # if j>0: # graph[board[i][j]].add(board[i][j-1]) # if j<length2-1: # graph[board[i][j]].add(board[i][j+1]) # ret=[] # for word in words: # if word[0] in graph: # self.dfs(graph,word,1,ret) # return ret # def dfs(self,graph,word,index,ret): # if index==len(word): # ret.append(word) # return # char = word[index] # if char not in graph[word[index-1]]: # return # self.dfs(graph,word,index+1,ret) if __name__=="__main__": s = Solution() print(s.wordSearchII(["doaf","agai","dcan"],["dog","dad","dgdg","can","again"])) print(s.wordSearchII(["doaf","agai","can"],["dog","dad","dgdg","can","again"])) print(s.wordSearchII(["a"],["b"])) print(s.wordSearchII(["abce","sfcs","adee"],["see","se"])) print(s.wordSearchII(["b","a","b","b","a"],["babbab","b","a","ba"])) print(s.wordSearchII(["abce","sfcs","adee"],["abcb","ninechapter","lintcode"])) print(s.wordSearchII(["abce","sfcs","adee"],["as","ab","cf","da","ee","e","adee","eeda"]))
#coding:utf-8 """ 题目描述: What you are given is a sentence like: “I am happy and sad” Please forget about how insane it is, just focusing on the following questions. And then some substitutes of some words are provided as well:[["happy", "glad"], ["glad", "good"], ["sad", "sorrow"]] which means happy can be replaced by glad while glad can continuously substituted by good and so on. Now, please write out all possible sentences with all substitutes. For example, by giving this specific case, your output should be like: I am happy and sad I am happy and sorrow I am glad and sad I am glad and sorrow I am good and sad I am good and sorrow """ import copy def make_sentence(ori_sentence, substitutes): """ ori_sentence: string, "I am happy and sad" substitutes: list of list, [["happy", "glad"], ["glad", "good"], ["sad", "sorrow"]] return: list of string """ if not ori_sentence or not substitutes or not len(substitutes[0]): print("Empty ori_sentence or substitutes") return words = ori_sentence.split(" ") sub = {k:v for [k,v] in substitutes} id_words = [] for word in words: temp = [] temp.append(word) if word in sub.keys(): while word in sub.keys(): temp.append(sub[word]) word = sub[word] id_words.append(temp) ret = [] helper(id_words, 0, ret) return [" ".join(item) for item in ret] def helper(id_words, depth, ret, sentence=[]): if len(sentence)==len(id_words): ret.append(copy.deepcopy(sentence)) else: for word in id_words[depth]: sentence.append(word) helper(id_words, depth+1, ret, sentence) sentence.pop() if __name__ == "__main__": ori_sentence = "I am happy and sad" substitutes = [["happy", "glad"], ["glad", "good"], ["sad", "sorrow"]] sentences = make_sentence(ori_sentence, substitutes) for st in sentences: print(st)