Introduction
- Can operate efficiently on both ends
- Be comfortable with with writing code on subarrays
- Sometimes may need a helper array to solve the problems
List in Python: list
in python is dynamically re-sized
Syntax
Python:1
2
3
4A.append(42)
A.remove(2) # O(n)
A.insert(3, 28) # O(n)
a in A # O(n)
JS:1
2
3
4A.push(42)
A.pop() // Remove from end
A.unshift(2) // Insert from start
A.shift() // Remove from start
Instantiate a 2-D array:
Python:1
2
3# Creates a list containing 5 lists, each of 8 items, all set to 0
w, h = 8, 5;
Matrix = [[0 for x in range(w)] for y in range(h)]# Creates a list containing 5 lists, each of 8 items, all set to 0
JS:1
const matrix = new Array(5).fill(0).map(() => new Array(4).fill(0)); // 5 rows, 4 columns matrix filled with 0
Copy a list in python
Shallow Copy
Python1
2newList = oldList[:]
newList = list(oldList)
Javascript1
2
3const A = [{'a': 1, 'b': 2}];
const B = A.slice(0);
const C = [...A];
Deep Copy
Python1
2from copy import deepcopy
newList = deepcopy(oldList)
Javascript1
let B = JSON.parse(JSON.stringify(A)); // Limitation: A can't contain undefined or functions
Methods
Python:1
2
3
4
5
6
7
8
9min(A)
max(A)
# Binary Search in a sorted array
bisect.bisect(A, 6)
A.reverse() # In place
A.sort() # In place
sorted(A) # Returns a copy
del A[i]
del A[i:j] # Removes the slice
Javascript:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44Math.min(...A);
// Reverse
B = A.reverse();
// From
B = Array.from('foo'); //['f', 'o', 'o']
// Concat: returns a new array
A = ['a', 'b', 'c'];
B = ['d', 'e', 'f'];
C = A.concat(B);
// Find: Return the first item in the array
A = [1, 2, 3]
A.find(ele => ele > 1) // return 2
// Filter
A = [1,2,3,4,5];
A.filter(ele => ele > 2); // return [3,4,5]
// Flat
A = [1, 2, [3, 4, [5, 6]]];
A.flat(); //[1, 2, 3, 4, [5, 6]]
// Alternative: reduce + concat
A.reduce((acc, val) => val.concat(acx), []); // Same as flat()
// forEach
A.forEach(ele => console.log(ele))
// Join
A = ['a', 'b','c'];
A.join(',');
// Map: returns a new array
A = [1,2,3];
B = A.map(ele => ele * 2);
// Reduce:
A = [1,2,3];
result = A.reduce((acc, val) => val + acx, 0) // 0 is the initial value
// The reducer function takes: acc, val, idx(current index), src(source array)
// Some: test whether at least one element in the array passes the function
A.some(ele => ele % 2 == 0); // true
Slicing and list comprehension
Python1
2
3
4
5A[k:] + A[:k] # Rotates A by k to the left
[x**2 for x in range(6) if x % 2 == 0]
[(x, y) for x in A for y in B]
[[x**2 for x in row] for row in M]
Javascriptslice()
provides a shallow copy of a portion of the original array.1
2
3A = [1,2,3,4,5];
A.slice(2); // [3,4,5]
A.slice(1,4); // [2,3,4]
Splice in javascript
The splice()
method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.
splice()
can be used to do:
- remove element from any index of array
- replace element from any index of array
- insert new element from any index of array
1 | let A = ['a', 'c', 'd']; |
Problems
Dutch National Flag
Leetcode: 75. Sort Colors
Solution
- Time: O(n), Space: O(1)
- Similiar to quick sort
- Set three dividers:
small
,cur
, andbig
- Divide the array into four sections: [0,0,1,1,???,2]
1 | var sortColors = function(nums) { |
Note:
if nums[cur] != 2
is used to avoid cases like[2,1,2]
where you could switch2
with2
and move forwardcur
, and left2
at a wrong place- Ending point is
cur <= r
1 | def sortColors(self, nums): |
Subarray problems
Kadane’s Algorith: Video: https://www.youtube.com/watch?v=86CQq3pKSUw
Permutation Problems
- Every permutation can be represented by a collection of independent permutations, each of which is cyclic, that is, it moves all elements by a fixed offset, wrapping around.
- There exist exactly
n!
permutations ofn
elements
EPI 5.10 Permutate the elements of an array
1 | def apply_permutation(perm, A): |
31. Next Permutation
Great Video: https://www.youtube.com/watch?v=GCm7m5671Ps
Find pattern
[Solution]:
- Find
k
such thatp[k] < p[k + 1]
and entries afterk
appear in decreasing order - Find the smallest
p[l]
such thatp[l] > p[k]
- Swap
p[l]
andp[k]
- Reverse the sequence after position
k
Note that decreasing order including p[k] = p[k + 1]
1 | def nextPermutation(nums: List[int]) -> None: |
1053. Previous Permutation With One Swap
Leetcode: https://leetcode.com/problems/previous-permutation-with-one-swap/
1 | def prevPermOpt1(self, A: List[int]) -> List[int]: |
Streaming data problems
295. Find Median from Data Stream
Leetcode: https://leetcode.com/problems/find-median-from-data-stream/
EPI 5.13 Sample Online Data
Design a program that takes a input of size k, and reads packets, continuously maintaining a uniform random subset of size k of the read packets.
1 | # Assumption: there are at least k elements in the stream. |
2D-Array Problems
To manipulate a 2D array, we always use left
, top
, right
, bottom
four pointers as boundaries.
48. Rotate Image
Leetcode: https://leetcode.com/problems/rotate-image/
1 | def rotate(self, matrix: List[List[int]]) -> None: |
54. Spiral Matrix
Leetcode: https://leetcode.com/problems/spiral-matrix/
1 | def spiralOrder(self, matrix: List[List[int]]) -> List[int]: |
1072. Flip Columns For Maximum Number of Equal Rows
Leetcode: https://leetcode.com/problems/flip-columns-for-maximum-number-of-equal-rows/
Solution:
Find the “pattern” of the row. “Pattern” here can be characterized by whether each element in the row is different with the first element or not.
1 | def maxEqualRowsAfterFlips(self, matrix: List[List[int]]) -> int: |
Duplicates or Missing numbers
448. Find All Numbers Disappeared in an Array
Leetcode: https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/
Find a missing number in O(n) time with no extra space:
1 | def findDisappearedNumbers(self, nums: List[int]) -> List[int]: |
442. Find All Duplicates in an Array
Leetcode: https://leetcode.com/problems/find-all-duplicates-in-an-array/
Note:
In order to achieve O(1) space, we use array itself as the marker of visited element.
1 | def findDuplicates(self, nums): |
Majority Element problem
Algorithm: Boyer-Moore Voting Algorithm
169. Majority Element
Leetcode: https://leetcode.com/problems/majority-element/
Video: https://www.youtube.com/watch?v=zOyOwDEF1Rc
1 | var majorityElement = function(nums) { |
229. Majority Element II
Leetcode: https://leetcode.com/problems/majority-element-ii/
Since the questions is asking element that has frequency < n / 3
, there are at most two answers in the result array. We can use two candidates and two counters to keep track of two most frequent element in the list.
443. String Compression
Leetcode: https://leetcode.com/problems/string-compression/
1 | var compress = function(chars) { |
Nested Array Problem
339. Nested List Weight Sum
Leetcode: https://leetcode.com/problems/nested-list-weight-sum/
1 | def depthSum(self, nestedList): |
364. Nested List Weight Sum II
Leetcode: https://leetcode.com/problems/nested-list-weight-sum-ii/
Instead of multiply the depth, we simply add sum from the previous level again in the next level with hist
representing history.
1 | def depthSumInverse(self, nestedList): |
341. Flatten Nested List Iterator
Leetcode: https://leetcode.com/problems/flatten-nested-list-iterator/
Error Case I:
1 | # input: [[]] |
Generator Solution1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class NestedIterator(object):
def __init__(self, nestedList):
"""
Initialize your data structure here.
:type nestedList: List[NestedInteger]
"""
self.list = nestedList
self.g = self.generator()
def generator(self):
while self.list:
cur = self.list.pop(0)
if cur.isInteger():
yield cur.getInteger()
else:
self.list = cur.getList() + self.list
def next(self):
"""
:rtype: int
"""
return next(self.g)
def hasNext(self):
try:
self.value = next(self.g)
return True
except StopIteration:
return False
Stack solution
Use a stack to flatten list. The index in each list represents the current element that’s dealing with.
1 | class NestedIterator(object): |
1 or 2 passes from left to right/right to left:
845. Longest Mountain in Array
Leetcode: https://leetcode.com/problems/longest-mountain-in-array/
My Solution: Look for the peak in range A[1, len(A) - 1]
, for each peak, we expand right and left border to get the maximum length.
1 | def longestMountain(self, A): |
Two-pass Solution: Use one up
array to remember the length of the continuous increasing sequence before i
, and use down
to remember the length of the continuous decreasing sequence after i
.
1 | def longestMountain(self, A: List[int]) -> int: |
One pass solution: Use two variables up
and down
to keep track of the length
of continuous increasing and decreasing subarrays. Reset them to 0
when meeting pivot points.
42. Trapping Rain Water
Leetcode: https://leetcode.com/problems/trapping-rain-water/
Note: Go from left to right and backwards, and keep finding left and right boundaries
1 | def trap(self, height): |
581. Shortest Unsorted Continuous Subarray
Leetcode: https://leetcode.com/problems/shortest-unsorted-continuous-subarray/
Note: Go forward to find the left boundary of unsorted elements, go backwards to find the right boundary of unsorted elements.
- determine the correct position of the minimum and the maximum element in the unsorted subarray to determine the boundaries of the required unsorted subarray.
- Time Complexity: O(N), Space: O(2N)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def findUnsortedSubarray(self, nums: List[int]) -> int:
forward = []
backward = []
left, right = float('inf'), -1
for i in range(len(nums)):
j = len(nums) - i - 1
while forward and forward[-1][1] > nums[i]:
left = min(left, forward.pop()[0])
forward.append([i, nums[i]])
while backward and backward[-1][1] < nums[j]:
right = max(right, backward.pop()[0])
backward.append([j, nums[j]])
# ! Remember the case when nums is already sorted
if left == float('inf') and right == -1:
return 0
return right - left + 1
121 Best Time to Buy and Sell Stock
152 Maximum Product Subarray
238 Product of Array Except Self
739 Daily Temperatures
769 Max Chunks to Make Sorted
770 Max Chunks to Make Sorted II
821 Shortest Distance to a Character
845 Longest Mountain in Array
LC 162, LC 852, see https://adonais0.github.io/20181024/leetcode-binary-search-recursion/
Array Manipulation Problem
189. Rotate Array
Leetcode: https://leetcode.com/problems/rotate-array/
Solve with TC = O(n) and space complexity = O(1)
Note:
- Start with
i = 0
, keep putting current element to the correct place, use atemp
variable to store the original element at the destination new i = (i + k) % n
1 | def rotate(self, nums: List[int], k: int) -> None: |