1769. Minimum Number of Operations to Move All Balls to Each Box
class Solution:
def minOperations(self, s: str) -> List[int]:
n = len(s)
total = 0
left = [0] * n
right = [0] * n
for i, v in enumerate(s):
if i > 0:
left[i] = total + left[i-1]
if v == '1':
total += 1
total = 0
for i, v in enumerate(s[::-1]):
if i > 0:
right[i] = total + right[i-1]
if v == '1':
total += 1
return [left[i]+right[n-1-i] for i in range(n)]
1298. Maximum Candies You Can Get from Boxes
class Solution:
def maxCandies(self, status: List[int], candies: List[int], keys: List[List[int]], containedBoxes: List[List[int]], initialBoxes: List[int]) -> int:
getBox = set(initialBoxes) # all the boxes we get but dont have the keys
getKey = set([]) # all the keys we get but does not have the box
canVisitBox = [] # for the boxes are open or we have the key
re = 0
visited = set()
# find all the box which can be visited (open status)
for i in initialBoxes:
if status[i]:
canVisitBox.append(i)
# loop all the boxes which can be visted
while canVisitBox:
j = canVisitBox.pop(0)
if j in visited:
continue
visited.add(j)
re += candies[j]
#
for box in containedBoxes[j]:
if status[box]:
canVisitBox.append(box)
else:
getBox.add(box)
for key in keys[j]:
getKey.add(key)
# print("getBox", getBox)
# print("getKey", getKey)
# if have box and key
needRemove = []
for i in getBox:
if i in getKey:
canVisitBox.append(i)
needRemove.append(i)
for j in needRemove:
getBox.remove(j)
getKey.remove(j)
# print("canVisitBox", canVisitBox)
return re
1329. Sort the Matrix Diagonally
class Solution:
def diagonalSort(self, mat: List[List[int]]) -> List[List[int]]:
# diagnoal share same i-j
# Time O(mn + (m+n)klogk), with k = min(m,n).
# Space O(MN)
n, m = len(mat), len(mat[0])
d = collections.defaultdict(list)
for i in range(n):
for j in range(m):
d[i-j].append(mat[i][j])
for k, v in d.items():
v.sort(reverse=True)
for i in range(n):
for j in range(m):
mat[i][j] = d[i-j].pop()
return mat
777. Swap Adjacent in LR String
class Solution:
def canTransform(self, start: str, end: str) -> bool:
'''
https://leetcode.com/problems/swap-adjacent-in-lr-string/discuss/217070/Python-using-corresponding-position-
'''
if len(start) != len(end): return False
A = [(s, idx) for idx, s in enumerate(start) if s == 'L' or s == 'R']
B = [(e, idx) for idx, e in enumerate(end) if e == 'L' or e == 'R']
if len(A) != len(B): return False
for (s, i), (e, j) in zip(A, B):
if s != e: return False
if s == 'L':
if i < j:
return False
if s == 'R':
if i > j:
return False
return True
1146. Snapshot Array
'''
Intuition
Instead of copy the whole array,
we can only record the changes of set.
Explanation
The idea is, the whole array can be large,
and we may take the snap tons of times.
(Like you may always ctrl + S twice)
Instead of record the history of the whole array,
we will record the history of each cell.
And this is the minimum space that we need to record all information.
For each A[i], we will record its history.
With a snap_id and a its value.
When we want to get the value in history, just binary search the time point.
Complexity
Time O(logS)
Space O(S)
where S is the number of set called.
SnapshotArray(int length) is O(N) time
set(int index, int val) is O(1) in Python and O(logSnap) in Java
snap() is O(1)
get(int index, int snap_id) is O(logSnap)
'''
class SnapshotArray(object):
def __init__(self, n):
self.A = [[[-1, 0]] for _ in range(n)] # [self.snap_id, val]
self.snap_id = 0
def set(self, index, val):
self.A[index].append([self.snap_id, val])
def snap(self):
self.snap_id += 1
return self.snap_id - 1
def get(self, index, snap_id):
i = bisect.bisect(self.A[index], [snap_id + 1]) - 1 # 因为搜索的是 [snap_id+1] 比[snap_id+1, val]都小
return self.A[index][i][1]
386. Lexicographical Numbers
class Solution(object):
def lexicalOrder(self, n):
def dfs(num):
if num > n: return
res.append(num)
for i in xrange(10):
if num*10 + i <= n:
dfs(num*10+i)
res = []
for i in xrange(1, 10): # 这里只需要遍历1~9
dfs(i)
return res