764. Largest Plus Sign
class Solution:
def orderOfLargestPlusSign(self, n: int, mines: List[List[int]]) -> int:
'''
找最长的十字架
Algorithms: For each position (i, j) of the grid matrix, we try to extend in each of the four directions (left, right, up, down) as long as possible, then take the minimum length of 1's out of the four directions as the order of the largest axis-aligned plus sign centered at position (i, j).
Optimizations: Normally we would need a total of five matrices to make the above idea work -- one matrix for the grid itself and four more matrices for each of the four directions. However, these five matrices can be combined into one using two simple tricks:
For each position (i, j), we are only concerned with the minimum length of 1's out of the four directions. This implies we may combine the four matrices into one by only keeping track of the minimum length.
For each position (i, j), the order of the largest axis-aligned plus sign centered at it will be 0 if and only if grid[i][j] == 0. This implies we may further combine the grid matrix with the one obtained above.
'''
grid = [[n] * n for i in range(n)]
for i, j in mines:
grid[i][j] = 0
for i in range(n):
l = r = u = d = 0
for j, k in zip(range(n), reversed(range(n))):
l = l + 1 if grid[i][j] != 0 else 0
grid[i][j] = min(l, grid[i][j])
r = r + 1 if grid[i][k] != 0 else 0
grid[i][k] = min(r, grid[i][k])
u = u + 1 if grid[j][i] != 0 else 0
grid[j][i] = min(u, grid[j][i])
d = d + 1 if grid[k][i] != 0 else 0
grid[k][i] = min(d, grid[k][i])
res = 0
for i in range(n):
for j in range(n):
res = max(res, grid[i][j])
return res
741. Cherry Pickup
class Solution:
def cherryPickup(self, grid: List[List[int]]) -> int:
# dp[x1][y1][x2] to represent the largest ans we can get when first guy (marked as A) at(x1, y2) and second guy(marked as B) at (x2, x1 + y1 - x2)
# because we can only go right and down, so we have x1 + y1 = x2 + y2 = total steps they go
# https://leetcode.com/problems/cherry-pickup/discuss/165218/Java-O(N3)-DP-solution-w-specific-explanation
# 2. Induction: every time we calculate the maximum of :
# * dp[x1 - 1][y1][x2] : A down, B right
# * dp[x1][y1 - 1][x2] : A right, B right
# * dp[x1 - 1][y1][x2 - 1]: A down, B down
# * dp[x1][y1 - 1][x2 - 1]: A right, B down
# if the Max of these values is negative, then we don't have a path to this point
# else we have: dp[x1][y1][x2] = Max + grid[x1 - 1][y1 - 1] + grid[x2 - 1][y2 - 1](if x1 != x2 && y1 != y2) else we
# only add once.
dp = [[[-1 for _ in grid] for _ in grid] for _ in grid]
dp[0][0][0] = grid[0][0] # base case A and B all in 0 0
n = len(grid)
for x1 in range(0, n):
for y1 in range(0, n):
for x2 in range(0, len(grid)):
y2 = x1 + y1 - x2
if x1 == y1 == x2 == 0 or y2 < 0 or y2 >= n or grid[x1][y1] == -1 or grid[x2][y2] == -1:
continue
pre_max = max(dp[x1-1][y1][x2], dp[x1][y1-1][x2], dp[x1-1][y1][x2-1], dp[x1][y1-1][x2-1])
if pre_max < 0:
continue
dp[x1][y1][x2] = pre_max + grid[x1][y1]
if x1 != x2:
dp[x1][y1][x2] = dp[x1][y1][x2] + grid[x2][y2]
print(x1, y1, x2, y2, dp[x1][y1][x2])
return max(0, dp[-1][-1][-1])
723. Candy Crush
class Solution(object):
def candyCrush(self, board):
# 只有横着或者竖着连续3个才可以消去。
# 把满足消去的设置为负数,比如2设置为-2,最后再一起消去
r, c = len(board), len(board[0])
found = True
while found:
found = False
for i in xrange(r):
for j in xrange(c):
val = abs(board[i][j])
if val == 0: continue
# check row
if i + 2 < r and abs(board[i+1][j]) == abs(board[i+2][j]) == val:
found = True
ii = i # 用ii 避免 下面的 i被修改了
while 0 <= ii < r and abs(board[ii][j]) == val: # 这里注意是ii
board[ii][j] = -val
ii += 1
# check col
if j + 2 < c and abs(board[i][j+1]) == abs(board[i][j+2]) == val:
found = True
while 0 <= j < c and abs(board[i][j]) == val:
board[i][j] = -val
j += 1
# 消去
if found:
for j in xrange(c):
emptyRow = r - 1
for i in xrange(r-1, -1, -1):
if board[i][j] > 0:
board[emptyRow][j] = board[i][j]
emptyRow -= 1
for i in xrange(emptyRow, -1, -1):
board[i][j] = 0
return board
562. Longest Line of Consecutive One in Matrix
class Solution(object):
def longestLine(self, M):
maxlen = 0
currlen = collections.defaultdict(int)
for i, row in enumerate(M):
for j, a in enumerate(row):
for key in i, j+.1, i+j+.2, i-j+.3: # j 是列相同的, i+j是anti-diagonals, i-j是diagonals
currlen[key] = (currlen[key] + 1) * a
# currlen[key] += 1*a 是错误的,如果不连续的要断开
maxlen = max(maxlen, currlen[key])
return maxlen
755. Pour Water
class Solution(object):
def pourWater(self, heights, V, K):
for _ in xrange(V):
idx = -1
# check left
for i in xrange(K-1, -1, -1):
if heights[i] > heights[i+1]:
break
elif heights[i] < heights[i+1]:
idx = i
if idx != -1:
heights[idx] += 1
continue
# check right
for i in xrange(K+1, len(heights)):
if heights[i] > heights[i-1]:
break
elif heights[i] < heights[i-1]:
idx = i
if idx != -1:
heights[idx] += 1
else:
heights[K] += 1
return heights
LeetCode - The World's Leading Online Programming Learning Platform
918. Maximum Sum Circular Subarray
class Solution(object):
def maxSubarraySumCircular(self, A):
total = curMax = curMin = 0
maxSum = float('-inf')
minSum = float('inf')
for n in A:
total += n
curMax = max(n, curMax+n)
maxSum = max(maxSum, curMax)
curMin = min(n, curMin+n)
minSum = min(minSum, curMin)
return max(maxSum, total - minSum) if maxSum > 0 else maxSum
825. Friends Of Appropriate Ages
class Solution(object):
def numFriendRequests(self, ages):
A = [0] * 121
re = 0
for age in ages:
A[age] += 1
# A < B <= 0.5A + 7, A < 0.5A + 7 A < 15 can not make friend request
for a in xrange(15, 121):
for b in xrange(int(0.5*a)+7+1, a+1):
re += A[a] * A[b] if a != b else A[a] * (A[b]-1)
return re
243. Shortest Word Distance
class Solution(object):
def shortestDistance(self, words, word1, word2):
i1 = i2 = -1
re = 5000
for idx, w in enumerate(words):
if w == word1:
i1 = idx
if w == word2:
i2 = idx
if i1 != -1 and i2 != -1:
re = min(re, abs(i1-i2))
return re
406. Queue Reconstruction by Height
class Solution(object):
def reconstructQueue(self, people):
d = {}
for h, k in people:
if h not in d:
d[h] = [[h, k]]
else:
d[h].append([h, k])
re = []
for h in sorted(d.keys(), reverse=True):
group = sorted(d[h])
if not re:
re += group
else:
for h, k in group:
re.insert(k, [h, k])
return re
128. Longest Consecutive Sequence
class Solution(object):
def longestConsecutive(self, nums):
d = {}
res = 0
for n in nums:
if n in d:
continue
left = d.get(n-1, 0)
right = d.get(n+1, 0)
Sum = left + right + 1
res = max(res, Sum)
d[n] = Sum
d[n-left] = Sum # 边缘的2个更新Sum就可以了,中间连续的不需要
d[n+right] = Sum
return res
718. Maximum Length of Repeated Subarray
DP解法
Given two integer arrays A
and B
, return the maximum length of an subarray that appears in both arrays.
Example 1:
Input:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
Output: 3
Explanation:
The repeated subarray with maximum length is [3, 2, 1].
dp[i][j] 的i,j是指的A,B的长度,而不是A,B的下标。比如dp[1][0]是指的长度为1的A 和长度为0的B的位置的比较。当i或者j为0时候,因为长度为0所以重复0,则dp为0. 遍历所有子串,记录重复的长度。
class Solution(object):
def findLength(self, A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: int
"""
dp = [[0]*(len(B)+1) for i in xrange(len(A)+1)]
maxLen = 0
for i in xrange(1, len(A)+1):
for j in xrange(1, len(B)+1):
if A[i-1] == B[j-1]:
dp[i][j] = dp[i-1][j-1]+1
maxLen = max(maxLen, dp[i][j])
else:
dp[i][j] = 0
return maxLen
795. Number of Subarrays with Bounded Maximum
DP
Suppose dp[i] denotes the max number of valid sub-array ending with A[i]. We use following example to illustrate the idea:
A = [2, 1, 4, 2, 3], L = 2, R = 3
- if A[i] < L
For example, i = 1. We can only append A[i] to a valid sub-array ending with A[i-1] to create new sub-array. So we have dp[i] = dp[i-1] (for i > 0)
- if A[i] > R:
For example, i = 2. No valid sub-array ending with A[i] exist. So we have dp[i] = 0.
We also record the position of the invalid number 4 here as prev.
- if L <= A[i] <= R
For example, i = 4. In this case any sub-array starts after the previous invalid number to A[i] (A[prev+1..i], A[prev+2..i]) is a new valid sub-array. So dp[i] += i - prev
Finally the sum of the dp array is the solution. Meanwhile, notice dp[i] only relies on dp[i-1] (and also prev), we can reduce the space complexity to O(1)
class Solution(object):
def numSubarrayBoundedMax(self, A, L, R):
"""
:type A: List[int]
:type L: int
:type R: int
:rtype: int
"""
dp = 0
prev = -1
res = 0
for i in xrange(len(A)):
if L<= A[i] <= R:
dp = i - prev
res += dp
elif A[i] < L:
res += dp
else:
dp = 0
prev = i
return res
分治法,第K小的数 O(n)
873. Length of Longest Fibonacci Subsequence
A sequence X_1, X_2, ..., X_n
is fibonacci-like if:
n >= 3
X_i + X_{i+1} = X_{i+2}
for alli + 2 <= n
Given a strictly increasing array A
of positive integers forming a sequence, find the length of the longest fibonacci-like subsequence of A
. If one does not exist, return 0.
(Recall that a subsequence is derived from another sequence A
by deleting any number of elements (including none) from A
, without changing the order of the remaining elements. For example, [3, 5, 8]
is a subsequence of [3, 4, 5, 6, 7, 8]
.)
Example 1:
Input: [1,2,3,4,5,6,7,8]
Output: 5
Explanation:
The longest subsequence that is fibonacci-like: [1,2,3,5,8].
Example 2:
Input: [1,3,7,11,12,14,18]
Output: 3
Explanation:
The longest subsequence that is fibonacci-like:
[1,11,12], [3,11,14] or [7,11,18].
dp[i][j] 表示以A[i] 和A[j]结尾的Fib序列的长度。则dp[i][j] = 以 A[j] 和 A[i]-A[j] 结尾的序列。所以要判断A[i]-A[j]是否在A中,并且,A【i】-A[j]要小于A【j】
第一次尝试,通过了23次时,时间超过限制:
class Solution(object):
def lenLongestFibSubseq(self, A):
"""
:type A: List[int]
:rtype: int
"""
dp = [[2]*i for i in A]
maxLen = 0
for i in xrange(len(A)):
for j in xrange(i):
if A[i] - A[j] < A[j] and (A[i]-A[j]) in A:
dp[i][j] = dp[j][A.index(A[i]-A[j])] + 1
maxLen = max(maxLen, dp[i][j])
return maxLen
改进后:
class Solution(object):
def lenLongestFibSubseq(self, A):
"""
:type A: List[int]
:rtype: int
"""
dp = collections.defaultdict(int)
maxLen = 0
s = set(A)
for i in xrange(len(A)):
for j in xrange(i):
if A[i] - A[j] < A[j] and (A[i]-A[j]) in s:
dp[A[i], A[j]] = dp.get((A[j], A[i]-A[j]), 2) + 1
maxLen = max(maxLen, dp[A[i], A[j]])
return maxLen
560. Subarray Sum Equals K
第一个解法,时间超过限制,但是简单易懂:
class Solution(object):
def subarraySum(self, nums, k):