Skip to main content

33 posts tagged with "Array"

View All Tags

· One min read
from typing import Callable


class Solution:
def evalRPN(self, tokens: list[str]) -> int:
stack: list[int] = []
operators: dict[str, Callable[[int, int], int]] = {
'+': lambda a, b: a + b,
'-': lambda a, b: a - b,
'*': lambda a, b: a * b,
'/': lambda a, b: int(a / b),
}
for token in tokens:
if token in operators:
b, a = stack.pop(), stack.pop()
stack.append(operators[token](a, b))
else:
stack.append(int(token))
return stack[0]

· One min read
class Solution:
def dailyTemperatures(self, temperatures: list[int]) -> list[int]:
result = [0] * len(temperatures)
stack = []
for r in range(len(temperatures)):
while stack and temperatures[stack[-1]] < temperatures[r]: # l < r
l = stack.pop()
result[l] = r - l
stack.append(r)
return result

· One min read
import heapq
from collections import Counter
from itertools import chain, islice


class Solution: # O(n) / O(n)
def topKFrequent(self, nums: list[int], k: int) -> list[int]:
buckets = [[] for _ in nums]
for n, c in Counter(nums).items():
buckets[-c].append(n)
return list(islice(chain.from_iterable(buckets), k))


class Solution1: # O(nlogn) / O(n)
def topKFrequent(self, nums: list[int], k: int) -> list[int]:
heap = []
for n, c in Counter(nums).items():
heapq.heappush(heap, (-c, n))
return [heapq.heappop(heap)[1] for _ in range(k)]


class Solution2: # O(nlogn) / O(n)
def topKFrequent(self, nums: list[int], k: int) -> list[int]:
heap = []
for n, c in Counter(nums).items():
heapq.heappush(heap, (-c, n))
return [x[1] for x in heapq.nsmallest(k, heap)]


class Solution3: # O(nlogn) / O(n)
def topKFrequent(self, nums: list[int], k: int) -> list[int]:
return [n for n, _ in Counter(nums).most_common(k)]

· One min read
class Solution1:
def rotate(self, nums: list[int], k: int) -> None:
if len(nums) > 1:
k %= len(nums)
nums[:-k], nums[-k:] = nums[-k:], nums[:-k]


class Solution:
def rotate(self, nums: list[int], k: int) -> None:
def reverse(start, stop):
for i in range((stop - start) // 2):
l, r = start + i, stop - 1 - i
nums[l], nums[r] = nums[r], nums[l]

k %= len(nums)
reverse(0, len(nums) - k)
reverse(len(nums) - k, len(nums))
reverse(0, len(nums))

· One min read
from ..notes import gcd


class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next


class Solution:
def insertGreatestCommonDivisors(self, head: ListNode) -> ListNode:
node = head
while node.next:
node.next = ListNode(val=gcd(node.val, node.next.val), next=node.next)
node = node.next.next
return head

· One min read
class Solution:
def maxSum(self, nums: list[int]) -> int:
ht: dict[int, list[int]] = {}
result = -1
for num in nums:
tmp, max_digit = num, 0
while tmp:
tmp, max_digit = tmp // 10, max(max_digit, tmp % 10)
ht[max_digit] = sorted(ht.get(max_digit, []) + [num])[-2:]
if len(ht[max_digit]) == 2:
result = max(result, sum(ht[max_digit]))
return result

· One min read
class Solution:
def threeSum(self, nums: list[int]):
result = set()
zero, neg, pos = counters = {}, {}, {}
for num in nums:
counter = counters[(num > 0) + (num != 0)]
counter[num] = counter.get(num, 0) + 1
# 0,0,0
if zero.get(0, 0) >= 3:
result.add((0, 0, 0))
# -,+,?
for n in neg:
for p in pos:
target: int = -(n + p)
counter = counters[(target > 0) + (target != 0)]
if target in counter:
triplet = tuple(sorted([n, p, target]))
if target in (n, p): # duplicate
if counter[target] >= 2:
result.add(triplet)
else:
result.add(triplet)
return result

· One min read
class Solution:
def search(self, nums: list[int], target: int) -> int:
lo, hi = 0, len(nums)
target_is_rotated = target < nums[0]
while lo < hi:
mid = (lo + hi) // 2
if nums[mid] == target:
return mid
mid_is_rotated = nums[mid] < nums[0]
if (mid_is_rotated, target_is_rotated) == (True, False): # [t] [m]
hi = mid
elif (mid_is_rotated, target_is_rotated) == (False, True): # [m] [t]
lo = mid + 1
# same side
elif nums[mid] > target:
hi = mid
else:
lo = mid + 1
return -1


class Solution1:
def search(self, nums: list[int], target: int) -> int:
# https://leetcode.com/problems/search-in-rotated-sorted-array/solutions/14435/clever-idea-making-it-simple/
lo, hi = 0, len(nums)
target_is_rotated = target < nums[0]
inf = (-1) ** target_is_rotated * float('inf')
while lo < hi:
mid = (lo + hi) // 2
if nums[mid] == target:
return mid
mid_is_rotated = nums[mid] < nums[0]
if (nums[mid], inf)[mid_is_rotated != target_is_rotated] > target:
hi = mid
else:
lo = mid + 1
return -1

· One min read
class Solution:
def searchMatrix(self, matrix: list[list[int]], target: int) -> bool:
M, N = len(matrix), len(matrix[0])
lo, hi = 0, M * N
while lo < hi:
mid = (lo + hi) // 2
row, col = divmod(mid, N)
if matrix[row][col] == target:
return True
if matrix[row][col] > target:
hi = mid
else:
lo = mid + 1
return False


class Solution1:
def searchMatrix(self, matrix: list[list[int]], target: int) -> bool:
M, N = len(matrix), len(matrix[0])
lo, hi = 0, M
while lo < hi:
mid = (lo + hi) // 2
if matrix[mid][0] == target:
return True
if matrix[mid][0] > target:
hi = mid
else:
lo = mid + 1
row = matrix[lo - 1]
lo, hi = 0, N
while lo < hi:
mid = (lo + hi) // 2
if row[mid] == target:
return True
if row[mid] > target:
hi = mid
else:
lo = mid + 1
return False

· One min read
from bisect import bisect_left


class SolutionDp: # O(n*n) / O(n)
def lengthOfLIS(self, nums: list[int]) -> int:
result, dp = 1, [1] * len(nums)
for i in range(len(nums)):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j] + 1)
result = max(result, dp[i])
return result


class SolutionBs: # O(n*log(n)) / O(n)
def lengthOfLIS(self, nums: list[int]) -> int:
result, dp = 0, [0] * len(nums)
for num in nums:
lo = bisect_left(dp, num, hi=result)
result, dp[lo] = max(result, lo + 1), num
return result


class SolutionBsLessSpace: # O(n*log(n)) / O(n)
def lengthOfLIS(self, nums: list[int]) -> int:
result, dp = 0, []
for i in range(len(nums)):
if dp and nums[i] <= dp[-1]:
dp[bisect_left(dp, nums[i])] = nums[i]
else:
result += 1
dp.append(nums[i])
return result


class SolutionBsInPlace: # O(n*log(n)) / O(1)
def lengthOfLIS(self, nums: list[int]) -> int:
result = 0
for i in range(len(nums)):
lo = bisect_left(nums, nums[i], hi=result)
result, nums[lo] = max(result, lo + 1), nums[i]
return result

· One min read
class Solution:
def asteroidCollision(self, asteroids: list[int]) -> list[int]:
s: list[int] = []
for a in asteroids:
s.append(a)
while len(s) > 1 and s[-2] > 0 > s[-1]:
if s[-2] == -s[-1]:
s.pop()
elif s[-2] < -s[-1]:
s[-2] = s[-1]
s.pop()
return s

· One min read
class SnapshotArray:
def __init__(self, length: int):
self._array: list[list[tuple[int, int]]] = [[(-1, 0)] for _ in range(length)]
self._snap_id = -1

def set(self, index: int, val: int) -> None:
self._array[index].append((self._snap_id, val))

def snap(self) -> int:
self._snap_id += 1
return self._snap_id

@staticmethod
def bs_r(a, t):
l, r = 0, len(a)
while l < r:
m = (l + r) // 2
if a[m] > t:
r = m
else:
l = m + 1
return l

def get(self, index: int, snap_id: int) -> int:
low = self.bs_r(self._array[index], (snap_id,))
return self._array[index][low - 1][1]

· One min read
from collections import deque
from heapq import heappop, heappush
from itertools import product
from sys import maxsize

cellT = tuple[int, int]
countT = int


class Solution1:
# [BFS] Runtime 1349 ms Beats 5.1%
def shortestPathBinaryMatrix(self, grid: list[list[int]]):
cellsT = set[cellT]

N = len(grid)
dummy_start_cell = (-1, -1)
bottom_right_cell = (N - 1, N - 1)

def find_adjacents(curr_row: int, curr_col: int):
def is_valid(cand_cell: cellT):
cand_row, cand_col = cand_cell
return (
0 <= cand_row < N
and 0 <= cand_col < N
and grid[cand_row][cand_col] == 0
)

cand_cells = (
(curr_row + row_offset, curr_col + col_offset)
for row_offset, col_offset in product(range(-1, 2), repeat=2)
)
return filter(is_valid, cand_cells)

queue: deque[cellsT] = deque([{dummy_start_cell}])
visiteds: cellsT = set()
count: countT = 1
while queue:
next_: cellsT = set()
q: cellsT = queue.popleft()
for cell in q:
visiteds.add(cell)
for adjacent in find_adjacents(*cell):
if adjacent in visiteds:
continue
if adjacent == bottom_right_cell:
return count
next_.add(adjacent)
if next_:
queue.append(next_)
count += 1
return -1


class Solution2:
# [dijkstra] Runtime 995 ms Beats 6.89%
def shortestPathBinaryMatrix(self, grid: list[list[int]]):
N = len(grid)
dummy_start_cell = (-1, -1)
bottom_right_cell = (N - 1, N - 1)

def find_adjacents(curr_row: int, curr_col: int):
def is_valid(cand_cell: cellT):
cand_row, cand_col = cand_cell
return (
0 <= cand_row < N
and 0 <= cand_col < N
and grid[cand_row][cand_col] == 0
)

cand_cells = (
(curr_row + row_offset, curr_col + col_offset)
for row_offset, col_offset in product(range(-1, 2), repeat=2)
)
return filter(is_valid, cand_cells)

heap: list[tuple[countT, cellT]] = [(0, dummy_start_cell)]
visiteds: set[cellT] = set()
while heap:
cost, vertex = heappop(heap)
if vertex == bottom_right_cell:
return cost
for new_vertex in find_adjacents(*vertex):
if new_vertex in visiteds:
continue
visiteds.add(new_vertex)
new_cost = cost + 1
heappush(heap, (new_cost, new_vertex))
return -1


class Solution3:
# [A*] Runtime 513 ms Beats 97.17%
def shortestPathBinaryMatrix(self, grid: list[list[int]]):
N = len(grid)
dummy_start_cell = (-1, -1)
bottom_right_cell = (N - 1, N - 1)

def find_adjacents(curr_row: int, curr_col: int):
def is_valid(cand_cell: cellT):
cand_row, cand_col = cand_cell
return (
0 <= cand_row < N
and 0 <= cand_col < N
and grid[cand_row][cand_col] == 0
)

cand_cells = (
(curr_row + row_offset, curr_col + col_offset)
for row_offset, col_offset in product(range(-1, 2), repeat=2)
)
return filter(is_valid, cand_cells)

def heuristic(cell_row: int, cell_col: int):
return max(abs(N - 1 - cell_row), abs(N - cell_col))

heap: list[tuple[countT, countT, cellT]] = [(-maxsize, 0, dummy_start_cell)]
costs: dict[cellT, countT] = {}
while heap:
estimate, cost, vertex = heappop(heap)
if vertex == bottom_right_cell:
return cost
for new_vertex in find_adjacents(*vertex):
new_cost = cost + 1
if costs.get(new_vertex, maxsize) > new_cost:
costs[new_vertex] = new_cost
new_estimate = new_cost + heuristic(*new_vertex)
heappush(heap, (new_estimate, new_cost, new_vertex))
return -1

· One min read
class Solution:
def mincostTickets(self, days: list[int], costs: list[int]) -> int:
day_costs = dict(zip([1, 7, 30], costs))
N = days[-1]
dp = [0] * (N + 1)
travel = set(days)
for i in range(1, N + 1):
if i in travel:
dp[i] = min(dp[max(0, i - d)] + c for d, c in day_costs.items())
else:
dp[i] = dp[i - 1]
return dp[-1]

· One min read
class Solution:
def spiralOrder(self, matrix: list[list[int]]) -> list[int]:
if not matrix or not matrix[0]:
return []
result = []
t, b, l, r = 0, len(matrix) - 1, 0, len(matrix[0]) - 1
while t <= b and l <= r:
result.extend([matrix[t][x] for x in range(l, r + 1)])
result.extend([matrix[x][r] for x in range(t + 1, b + 1)])
if t < b and l < r:
result.extend([matrix[b][x] for x in range(r - 1, l, -1)])
result.extend([matrix[x][l] for x in range(b, t, -1)])
t, b, l, r = t + 1, b - 1, l + 1, r - 1
return result

· One min read
class Solution1:
def removeDuplicates(self, nums: list[int]) -> int:
v, p = -101, 0 # ng
for i in range(len(nums)):
if nums[i] > v:
v = nums[p] = nums[i]
p += 1
return p


class Solution:
def removeDuplicates(self, nums: list[int]) -> int:
p = 1
for i in range(1, len(nums)):
if nums[p - 1] < nums[i]:
nums[p], p = nums[i], p + 1
return p