sophryu99 / algorithm Goto Github PK
View Code? Open in Web Editor NEWalgorithm in python - 4 questions a week
algorithm in python - 4 questions a week
https://leetcode.com/problems/palindromic-substrings/description/
Expansion from center approach
Given the length of the string is N
, the number of possible center points are 2N - 1
. Between S[0] and S[1], at S[1], between S[1] and S[2], at S[2], etc.
2N - 1
centers, and have the left and the right pointers to cover both cases where the center point overlaps, or are consecutive pointsLeft = i // 2
, Right = (i+1)//2
class Solution:
def countSubstrings(self, s):
cnt = 0
N = len(s)
for i in range(2 * N - 1):
left = i // 2
right = (i + 1) // 2
while 0 <= left and right < N and s[left] == s[right]:
left -= 1
right += 1
cnt += 1
return cnt
N: length of the string
O(N^2)
as worst case there will be an expansion till the end of the string for every letter, aaa
O(1)
no extra space usedhttps://leetcode.com/problems/insert-delete-getrandom-o1/description/
The intuition would be to create a set for O(1)
operation. However, since there is the function getRandom()
, creating a set is not efficient as we would first need to convert to list, which will be an overhead for the whole code. This is because set is actually not random as when using integers, elements are popped from the set in the order they appear in the underlying hashtable.
{int element: index}
, and list to keep track of unique int elementsimport random
class RandomizedSet:
def __init__(self):
self.d = {}
self.l = []
def insert(self, val: int) -> bool:
if val not in self.d:
# Store the index of the int ele
self.d[val] = len(self.l)
self.l.append(val)
return True
return False
def remove(self, val: int) -> bool:
if val not in self.d:
return False
l_ele = self.l[-1]
r_index = self.d[val]
# Replace the index
self.d[l_ele] = r_index
self.l[r_index] = l_ele
# Remove from list and dict
self.l[-1] = val
self.l.pop()
self.d.pop(val)
return True
def getRandom(self) -> int:
return random.choice(self.l)
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
Example
element_to_remove = 7
before: [4, 7, 9, 3, 5]
after: [4, 5, 9, 3]
before: {4:0, 7:1, 9:2, 3:3, 5:4}
after: {4:0, 9:2, 3:3, 5:1}
n: array size
O(1)
with pop, add and get random operationO(n)
with dict and listhttps://leetcode.com/problems/reverse-linked-list/
# First Iteration------
Initial head: ListNode{val: 1, next: ListNode{val: 2, next: ListNode{val: 3, next: None}}}
# Create a copy of the original ListNode head
curr: ListNode{val: 1, next: ListNode{val: 2, next: ListNode{val: 3, next: None}}}
# Rotate the original head
head reset: ListNode{val: 2, next: ListNode{val: 3, next: None}}
# Set the curr.next as prev which contains the curr state before this iteration
curr: ListNode{val: 1, next: None}
# Set prev as the current rotated array
prev: ListNode{val: 1, next: None}
# Second Iteration------
Initial head: ListNode{val: 2, next: ListNode{val: 3, next: None}}
curr: ListNode{val: 2, next: ListNode{val: 3, next: None}}
head reset: ListNode{val: 3, next: None}
curr: ListNode{val: 2, next: ListNode{val: 1, next: None}}
prev: ListNode{val: 2, next: ListNode{val: 1, next: None}}
# Third Iteration-----
Initial head: ListNode{val: 3, next: None}
curr: ListNode{val: 3, next: None}
head reset: None
curr: ListNode{val: 3, next: ListNode{val: 2, next: ListNode{val: 1, next: None}}}
prev: ListNode{val: 3, next: ListNode{val: 2, next: ListNode{val: 1, next: None}}}
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev = None
while head:
# Create a copy of the whole ListNode
curr = head
# Rotate the head LL
head = head.next
# Set the curr.next as prev which contains the curr state before this iteration
curr.next = prev
# Set prev as the current rotated array
prev = curr
return prev
n: number of nodes
O(n)
Search through the ListNodeO(n)
Copy of the ListNodehttps://leetcode.com/problems/product-of-array-except-self/
The key is to write an algorithm in O(n)
time without using the division operation. If division operation was allowed, the simplest approach would have been getting the product of every elements in the array, and dividing by ith element.
arr
, update the base var as base * arr[i]
.base
var as base * nums[i]
def productExceptSelf(self, nums: List[int]) -> List[int]:
ans = []
n = len(nums)
base = 1
# Scan from the left
for i in range(n):
ans.append(base)
base = base * nums[i]
# Scan from the right
base = 1
for i in range(n-1,-1,-1):
ans[i] = ans[i] * base
base = base * nums[i]
return ans
n: length of the array
O(n)
Twice of linear scan through the arrayO(n)
answer arrayhttps://leetcode.com/problems/binary-search-tree-iterator/
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
self.stack = []
self.pushLeft(root)
def pushLeft(self, root):
while root:
self.stack.append(root)
root = root.left
# Moves the pointer to the right
def next(self) -> int:
node = self.stack.pop()
# Move the pointer to right
self.pushLeft(node.right)
return node.val
def hasNext(self) -> bool:
return len(self.stack) > 0
https://leetcode.com/problems/all-paths-from-source-to-target/description/
DFS through the DAG
Since the size of the input node is 2 <= n <= 15
, the approach does not need to be super efficient
class Solution:
def allPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
def dfs(path):
if path[-1] == len(graph) - 1:
res.append(path)
return
for v in graph[path[-1]]:
dfs(path + [v])
res = []
dfs([0])
return res
n: number of edges
O(n)
- O(n^2)
depending on the shape of the DAGO(n)
as result arrayhttps://leetcode.com/problems/lru-cache/description/
The functions get and put must each run in O(1)
average time complexity.
Ordered dict approach
Ordered dict: dictionary subclass specially designed to remember the order of items, which is defined by the insertion order of keys.
(key, val)
in the input orderGet
method: returns the value associated with a key, moves the called key to the end of the dictPut
method: If the current length of the dict exceeds the capacity, pop the first element from the dictionary. Update the value to the dict.from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self.size = capacity
self.cache = OrderedDict()
def get(self, key):
if key not in self.cache:
return -1
val = self.cache[key]
self.cache.move_to_end(key) # Ordered dict internal function
return val
def put(self, key, val):
if key in self.cache:
del self.cache[key]
self.cache[key] = val
if len(self.cache) > self.size:
self.cache.popitem(last=False)
N: number of input cache
O(1)
with only add, del, move to end operationO(N)
https://leetcode.com/problems/minimum-number-of-steps-to-make-two-strings-anagram/description/
Anagram: Words that can be rearranged to form each others
from collections import defaultdict
class Solution:
def minSteps(self, s: str, t: str) -> int:
s_dict = defaultdict(int)
t_dict = defaultdict(int)
for i in range(len(s)):
s_dict[s[i]] += 1
t_dict[t[i]] += 1
s_count = len(set(s_dict))
t_count = len(set(t_dict))
res = 0
if s_count > t_count:
for item in s_dict:
if item in t_dict:
s_dict[item] = max(0, s_dict[item] - t_dict[item])
res = sum(s_dict.values())
else:
for item in t_dict:
if item in s_dict:
t_dict[item] = max(0, t_dict[item] - s_dict[item])
res = sum(t_dict.values())
return res
N: length of the strings
O(n)
linear scan through the stringsO(n)
dictionarieshttps://leetcode.com/problems/binary-search-tree-iterator/description/
Left -> Root -> Right
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
# In order traversal: Left -> Root -> Right
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
self.stack = []
self.pushLeft(root)
def pushLeft(self, root):
while root:
self.stack.append(root)
root = root.left
def next(self) -> int:
node = self.stack.pop()
# Move the pointer to right
self.pushLeft(node.right)
return node.val
def hasNext(self) -> bool:
return len(self.stack) > 0
# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
n: number of nodes
Time Complexity: O(n)
Memory: O(n)
from collections import deque
class Solution:
def levelOrder(self, root):
if not root: return []
queue, res = deque([root]), []
# Append the root to the deque
while queue:
# For the current level, iterate through all node and pop the root node
cur_level, size = [], len(queue)
for _ in range(size):
node = queue.popleft()
# If there is left chid, append to the queue
if node.left:
queue.append(node.left)
# If there is right chid, append to the queue
if node.right:
queue.append(node.right)
# Append the current root node's val to the current level array
cur_level.append(node.val)
# Append the current level's val to the res
res.append(cur_level)
return res
n: number of node
O(n)
visiting every node onceO(n)
size of the qhttps://leetcode.com/problems/two-city-scheduling/description/
Send everyone to the first city first, and send the half to the other city which has the least difference between the costs
class Solution:
def twoCitySchedCost(self, costs: List[List[int]]) -> int:
diff = []
totalsum = 0
for i, cost in enumerate(costs):
diff.append(cost[1] - cost[0])
totalsum += cost[0]
# sort by the differences
diff.sort()
for i in range(len(costs) // 2):
totalsum += diff[i]
return (totalsum)
O(nlog(n))
-> sort()O(n)
https://leetcode.com/problems/flatten-a-multilevel-doubly-linked-list/description/
Key idea: binary tree preorder traversal, regarding child as left child, next as right child. Need to get rid of child, and flatten the DLL so that every Node is either prev or next.
next
and child
in that order.class Solution:
def flatten(self, head):
if not head: return head
stack, order = [head], []
while stack:
last = stack.pop()
order.append(last)
if last.next:
stack.append(last.next)
if last.child:
stack.append(last.child)
for i in range(len(order) - 1):
order[i+1].prev = order[i]
order[i].next = order[i+1]
order[i].child = None
return order[0]
Example:
Input DLL : [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]
Order List: [1, 2, 3, 7, 8, 11, 12, 9, 10, 4, 5, 6]
n: number of nodes
O(n)
- visits every node onceO(n)
- stackhttps://leetcode.com/problems/maximum-product-subarray/description/
Main idea is to keep track of the max product and min product as the array contains positive and negative numbers.
We have three choices to make in the array:
class Solution:
def maxProduct(self, nums: List[int]) -> int:
max_prod, min_prod, ans = nums[0], nums[0], nums[0]
for i in range(1, len(nums)):
x = max(nums[i], max_prod*nums[i], min_prod*nums[i])
y = min(nums[i], max_prod*nums[i], min_prod*nums[i])
max_prod, min_prod = x, y
ans = max(max_prod, ans)
return ans
n: size of nums array
O(n)
linear scan through the arrayO(1)
no extra space usedhttps://leetcode.com/problems/add-two-numbers-ii/description/
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
stck1, stck2 = [], []
while l1:
stck1.append(l1.val)
l1 = l1.next
while l2:
stck2.append(l2.val)
l2 = l2.next
num1 = int(''.join([str(i) for i in stck1]))
num2 = int(''.join([str(i) for i in stck2]))
summ = list(str(num1 + num2))
head = None
for i in range(len(summ) - 1, -1, -1):
#create a new node to hold the data
new_node = ListNode(int(summ[i]))
#set the next of the new node to the current head
new_node.next = head
#set the head of the Linked List to the new head
head = new_node
return head
N: length of string1, M: length of string2
O(N + M)
Loop through the stringO(N + M)
with new ListNodehttps://leetcode.com/problems/coin-change/description/
dp[i]
: fewest number of coins that sums to ii (the amount to be summed up to)
, iterate through the coin array and checki
, get the dp[i - coin]
value, and compare it with the current dp[i]
val. Reset dp[i]
with smaller value -> dp[i] = min(dp[i], dp[i - coin] + 1)
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
# BFS approach
# dp array with the size of amount
# dp[i] is the fewest number of coins need to sum up to i
dp = [0] + [float('inf')] * amount
for i in range(1, amount + 1):
for coin in coins:
if i - coin >= 0:
dp[i] = min(dp[i], dp[i - coin] + 1)
if dp[-1] == float('inf'):
return -1
return dp[-1]
N: amount, M: number of coins
O(N * M)
as for every amount, every coins are tried outO(N)
dp array of size Nimport heapq
from collections import defaultdict
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
d = defaultdict(int)
for num in nums:
d[num] += 1
heap = []
for key in d:
# To convert to maxheap
heapq.heappush(heap, (-d[key], key))
res = []
# Get the k top most elements from the heapq
for _ in range(k):
p = heapq.heappop(heap)
res.append(p[1])
return res
O(n)
max heapO(n)
https://leetcode.com/problems/design-an-ordered-stream/description/
We need to store n
incoming value (idKey, value)
at the given index. And with every incoming index, we have to check
Approach
class OrderedStream:
def __init__(self, n):
self.stream = [None]*n
self.ptr = 0
def insert(self, idKey, value):
idKey -= 1
self.stream[idKey] = value
if self.ptr < idKey:
return []
else:
while self.ptr < len(self.stream) and self.stream[self.ptr] is not None:
self.ptr += 1
return self.stream[idKey:self.ptr]
# Your OrderedStream object will be instantiated and called as such:
# obj = OrderedStream(n)
# param_1 = obj.insert(idKey,value)
O(1)
insertion and slicing of arrayO(n)
for the stream arrayhttps://leetcode.com/problems/house-robber/
Memoization
m[k] = money at the kth house
p[k] = profit at kth house
p[0] = 0, p[1] = m[1]
p[k] = max(p[k-2] + m[k], p[k-3] + m[k])
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
elif len(nums) == 2:
return max(nums)
# Create a copy of the original nums array
p = [0] * (len(nums) + 1)
p[0] = 0
p[1] = nums[0]
p[2] = nums[1]
for i in range(3, len(p)):
p[i] = max(p[i - 3]+ nums[i - 1], p[i - 2] + nums[i - 1])
return max(p)
n: array size
O(n)
O(n)
https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/
['', 0]
pair. The pair indicates [letter, count]
class Solution:
def removeDuplicates(self, s, k):
stck = [['', 0]]
for l in s:
if stck[-1][0] == l:
stck[-1][1] += 1
if stck[-1][1] == k:
stck.pop()
else:
stck.append([l, 1])
return (''.join([i * j for i, j in stck]))
n: length of string s
O(n)
-> Linear scan through the stringO(n)
-> Stackhttps://leetcode.com/problems/search-in-rotated-sorted-array/description/
mid = (left + right ) // 2
arr[mid] > arr[left]
:nums[left] <= target < nums[mid]
reset right index right = mid - 1
left = mid + 1
arr[mid] < arr[left]
nums[mid] < target and target <= nums[right]
, reset left index left = mid + 1
right = mid - 1
"""
Binary Search
nums = [3,4,5,6,0,1,2], target = 3
"""
class Solution:
def search(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
# If the current number is larger than the target, move the window
"""
Determine if the array is left rotated or right rotated
Original
1 2 3 4 5
mid
Left-rotated -> arr[mid] > arr[left]
2 3 4 5 1
mid
Right-rotated -> arr[mid] < arr[left]
5 1 2 3 4
mid
"""
# The array is left rotated
if nums[mid] >= nums[left]:
# If the target number is in between the left side of the array, reset right index to continue search on the left side
if nums[left] <= target and target < nums[mid]:
right = mid - 1
else:
left = mid + 1
# The array is right rotated
else:
# If the target number is in between the right side of the array, reset left index to continue search on the right side
if nums[mid] < target and target <= nums[right]:
left = mid + 1
else:
right = mid - 1
# If not in the array
return -1
n: length of the array
O(log(n))
binary searchO(1)
no extra space usedhttps://leetcode.com/problems/knight-dialer/description/
A knight could only move in either 2 horizontal + 1 vertical
or 2 vertical + 1 horizontal
.
Graph traversal, DP problem with N stops
i in range(n)
), create a next array of [0] * 10
where next[i] = count of dial pad that can be reached from dial pad i
First iteration
0 [2, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1 [2, 2, 0, 0, 0, 0, 0, 0, 0, 0]
2 [2, 2, 2, 0, 0, 0, 0, 0, 0, 0]
3 [2, 2, 2, 2, 0, 0, 0, 0, 0, 0]
4 [2, 2, 2, 2, 3, 0, 0, 0, 0, 0]
5 [2, 2, 2, 2, 3, 0, 0, 0, 0, 0]
6 [2, 2, 2, 2, 3, 0, 3, 0, 0, 0]
7 [2, 2, 2, 2, 3, 0, 3, 2, 0, 0]
8 [2, 2, 2, 2, 3, 0, 3, 2, 2, 0]
9 [2, 2, 2, 2, 3, 0, 3, 2, 2, 2]
dp
array, and continue with the next iterationclass Solution:
def knightDialer(self, n: int) -> int:
dct = {
0:(4,6),
1:(6,8),
2:(7,9),
3:(4,8),
4:(0,3,9),
5:(),
6:(0,1,7),
7:(2,6),
8:(1,3),
9:(2,4)
}
num_keys = 10
dp = [1] * num_keys # dp[i] = number of times the knight can reach dial pad i
for _ in range(n - 1):
nxt = [0] * num_keys
for i in dct:
for j in dct[i]:
nxt[i] += dp[j]
dp = nxt
return sum(dp) % (10**9 + 7)
N: input size N
O(N * number of dials in dial pad(10) * max size of dict[i] (3) )
-> O(N)
O(1)
with dp array of size 10https://leetcode.com/problems/longest-repeating-character-replacement/description/
r - l + 1
, then subtract the MAXIMUM frequency. See if this is <= K for validity.https://leetcode.com/problems/design-browser-history/description/
Rather unclear description for the visit() function.
array[curr_pointer:]
as the function clears the forward history, append new urllass BrowserHistory:
def __init__(self, homepage: str):
self.history = [homepage]
self.pointer = 0
def visit(self, url: str) -> None:
self.pointer += 1
self.history = self.history[:self.pointer]
self.history.append(url)
def back(self, steps: int) -> str:
self.pointer = max(self.pointer - steps, 0)
return self.history[self.pointer]
def forward(self, steps: int) -> str:
self.pointer = min(self.pointer + steps, len(self.history) - 1)
return self.history[self.pointer]
# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)
N: number of urls
O(1)
with just simple append, return from a stackO(n)
stack sizehttps://leetcode.com/problems/decode-string/
When we hit an open bracket, we know we have parsed k for the contents of the bracket, so push (current_string, k)
to the stack, so we can pop them on closing bracket to duplicate the enclosed string k times.
(string element, k)
k = k * 10 + int(char)
class Solution:
def decodeString(self, s: str) -> str:
stck = []
curr_string = ""
k = 0
for char in s:
if char.isdigit():
k = k * 10 + int(char)
elif char == '[':
stck.append((curr_string, k))
curr_string = ""
k = 0
elif char == ']':
last_string, last_k = stck.pop(-1)
curr_string = last_string + last_k * curr_string
else:
curr_string += char
return curr_string
N: length of the string
O(N)
linear scan through the stringO(N)
size of stackhttps://leetcode.com/problems/longest-palindromic-substring/
class Solution:
def longestPalindrome(self, s: str) -> str:
res = ""
for i in range(len(s)):
# Get the longer string from the search
res = max(self.helper(i, i, s), self.helper(i, i + 1, s), res, key = len)
return res
def helper(self, l, r, s):
while 0 <= l and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return s[l + 1: r]
n: length of the string
Time Complexity: O(n^2)
-> Worst case search through every element of the string
Memory: O(1)
https://leetcode.com/problems/number-of-islands/description/
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically.
BFS Approach
grid[i][j]
, initiate bfs if it is 1.grid[i][j]
by flipping the '1' value to 0.from collections import deque
class Solution:
def numIslands(self, grid):
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1':
grid[i][j] = 0 # Mark as visited
self.bfs(grid, i, j) # turn the adjancent '1' to '0'
count += 1
return count
def bfs(self,grid, i, j):
queue = deque([])
queue.append((i,j))
while queue:
qr, qc = queue.popleft()
directions = [[1,0],[-1,0],[0,1],[0,-1]]
for dr, dc in directions:
nr, nc = qr + dr, qc + dc
if 0 <= nr < len(grid) and 0 <= nc < len(grid[0]) and grid[nr][nc] == '1':
queue.append((nr,nc))
grid[nr][nc] = 0 # Mark as visited
N: number of elements, M: length of each elements
O(N*M)
Visiting every elements in the grid at most onceO(N*M)
Queue size{customerId: (stationName, time)}
, keep track of the customerId as the key, and the checked-in station name and time{(startstation, endstation): total time spent between}
, keep track of the total time spent between two stations. This is calculated when a customer checks out.{(startstation, endstation): number of trips}
, keep track of the frequency of the trips between two stations. This is calculated when a customer checks outfrom collections import defaultdict
class UndergroundSystem:
def __init__(self):
# {customerId: (stationName, time)}
self.customer = {}
# {(startstation, endstation): total time spent between}
self.pairs = defaultdict(int)
# {(startstation, endstation): number of trips}
self.freqs = defaultdict(int)
def checkIn(self, id: int, stationName: str, t: int) -> None:
self.customer[id] = (stationName, t)
def checkOut(self, id: int, stationName: str, t: int) -> None:
# Get the stationName and the time associated with the customerId
startstation, startTime = self.customer.pop(id)
self.freqs[(startstation, stationName)] += 1
self.pairs[(startstation, stationName)] += t - startTime
def getAverageTime(self, startStation: str, endStation: str) -> float:
return self.pairs[(startStation, endStation)] / self.freqs[(startStation, endStation)]
# Your UndergroundSystem object will be instantiated and called as such:
# obj = UndergroundSystem()
# obj.checkIn(id,stationName,t)
# obj.checkOut(id,stationName,t)
# param_3 = obj.getAverageTime(startStation,endStation)
n: number of inputs
O(1)
simple calculation, insertion and removalO(n)
, dictionarieshttps://leetcode.com/problems/word-search/description/
(i, j, grid, word)
as input param. For every iteration, check if grid[i][j] == word[0]
and if i, j is within the grid range. Mark grid[i][j] = '#'
and unmark when the dfs is done.from collections import Counter
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
# Count number of letters in board and store it in a dictionary
boardDic = defaultdict(int)
for i in range(len(board)):
for j in range(len(board[0])):
boardDic[board[i][j]] += 1
# Count number of letters in word
# Check if board has all the letters in the word and they are atleast same count from word
wordDic = Counter(word)
for c in wordDic:
if c not in boardDic or boardDic[c] < wordDic[c]:
return False
# Traverse through board and if word[0] == board[i][j], call the DFS function
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] == word[0]:
if self.dfs(i, j, 0, board, word):
return True
return False
def dfs(self, i, j, k, board, word):
# Recursion will return False if (i,j) is out of bounds or board[i][j] != word[k] which is current letter we need
if i < 0 or j < 0 or i >= len(board) or j >= len(board[0]) or \
k >= len(word) or word[k] != board[i][j]:
return False
# If this statement is true then it means we have reach the last letter in the word so we can return True
if k == len(word) - 1:
return True
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
for x, y in directions:
# Since we can't use the same letter twice, I'm changing current board[i][j] to -1 before traversing further
tmp = board[i][j]
board[i][j] = -1
# If dfs returns True then return True so there will be no further dfs
if self.dfs(i + x, j + y, k + 1, board, word):
return True
board[i][j] = tmp
N: number of items in the array, M: length of every items, L: length of the word
O(N *M)
O(L)
counter dicthttps://leetcode.com/problems/merge-intervals/
prev[-1] >= curr[0]
, create a new interval with [min(prev[0], curr[0], max(prev[1], curr[1])]
to cover the maximum range. Replace the top most interval with the new intervalclass Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
# Sort by the first element asc
intervals.sort(key = lambda pairs: pairs[0])
stck = [intervals[0]]
for i in range(1, len(intervals)):
prev = stck[-1]
if prev[1] >= intervals[i][0]:
new_interval = [min(prev[0], intervals[i][0]), max(prev[1], intervals[i][1])]
stck[-1] = new_interval
else:
stck.append(intervals[i])
return stck
N: array size
O(N)
linear scan of the arrayO(N)
stack sizehttps://leetcode.com/problems/min-stack/description/
The insight is to keep track of the minimum value so far and push it, along with the number we are pushing, onto the stack.
(number we are pushing, the minimum value so far)
to the stackpop
and get from a stack has a constant time complexityclass MinStack:
def __init__(self):
self.q = []
def push(self, val: int) -> None:
if self.q:
minval = self.q[-1][1]
if val < minval:
self.q.append((val, val))
else:
self.q.append((val, minval))
else:
self.q.append((val, val))
def pop(self) -> None:
# O(1)
self.q.pop()
def top(self) -> int:
# O(1)
return self.q[-1][0]
def getMin(self) -> int:
# O(1)
if len(self.q) == 0:
return None
return self.q[-1][1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
n: number of values
O(1)
O(n)
stackA declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.