0% found this document useful (0 votes)
24 views

Leetcode 75

leetcode
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views

Leetcode 75

leetcode
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 6

String:

Valid Parathenses: Use stack.


If ( { [, push
If ) ] }
- But stack empty, return false
- But s.top() is not ) ] } accordingly, return false
else s.pop();
In the end, if !s.empty(), return false

Valid Palindrome: Input: s = "A man, a plan, a canal: Panama"


Output: true
Explanation: "amanaplanacanalpanama" is a palindrome.
-> Solution: traverse inside a while/for loop with condition right > left, be
careful! This is not easy as it seems.

468. Valid IP Address:


- Write a split function return parts: vector<string> split(string & s)
- Bool isIPv4:
+ if parts.size != 4, return false.
+ if (part.empty() || part.size() > 3 || part.size() > 1 && part[0] ==
'0') // check leading 0s
+ for (auto i : part) if !isdigit return false
+ if (stoi(part) > 255) return false
- Bool isIPv6:
+ if parts.size() !8 return false
+ if (part.empty() || part.size() > 4) return false
+ for (auto i : part) if !isxdigit return false

Valid anagram: Use array of 75, (int)s[i] - 48, O(n), O(75). Or use unordered_map
for universal unicode, check for 0, O(n), O(n) values.

firstNonRepeatingCharacter: "abcab" -> 'c', "abcabc" -> '_'. Solution: Use hash to
store key: char, value: freq, position to avoid O(2N) looping, but O(3N) data
structure. Or: Use array[26]. 'a'- 98 = 0.

Word Ladder I: Input: beginWord = "hit", endWord = "cog", wordList =


["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: One shortest transformation sequence is "hit" -> "hot" -> "dot" ->
"dog" -> cog", which is 5 words long.
-> Solution: Use BFS. Trick: Calculate size of queue, use for loop for that
size (this keep the level constant without having to store level somewhere else).
Use for (char c='a';c<=z;c++) to loop characters. O(M*26*N)

Longest Repeating Character:


-> // Solution O(26n)
// Keep a sliding window (l,r). If the length of sliding window r-l+1 minus
maximum frequency of a word is less
// than k (this means we can still replace), we expand window to the right: r+
+. Else, shirnk window by increasing
// left: l++. The maximium frequency is calculating by just looping a[26].
a[26] store frequency of chars in sliding
// window. When handling increment, if r++ then we add next char, calculating
curMax, if l++ then we dont do that.
-> // Solution O(n): To avoid looping a[26], the maximium frequency is
calculating by maxF = max(maxF, frequency of current word just being modified),
because length of current word r-l+1 - maxF <= k if maxF is always valid. If
frequency increase, we update it. If frequency decrease, we don't care.
394. Decode String:
-> Stack: ...
-> Recursion: string helper(int & pos, const string & s)
- If see '[', helper subproblem, then add num times the repeatedString
to word
- If see ']', return word
- If see digit >= '0' && <= '9', add to num: num = num*10 + s[pos] -'0'
- If see regular characters, add to word
- Return word;

Valid Parenthesis String 678:


-> Greedy, counting balance both max and min. Max is when * = (, min is *
= ).
- If high < 0, return false (unpaired close parenthesis)
- low = max(low, 0), can't have negative number of ), so * = "" instead
- return if low == 0 or not.

Group Anagram:
-> Solution 1: O(N*K*26): key is "98979797979710097....97" represent "aggg"
value is the string itself
-> Solution 2: O(N*K*log(K)): counting sort. Sort words then keep track of
similar group

1209. Remove adjacent duplicates in string


-> O(N): Stack
- Stack of pair <int, char>. Int is the number of times when we use append.
char is character
- loop through string s
+ if stack.top() != c, stack.push(1,c)
+ else stack.top().first++;
if st.top().first == k; st.pop();
- // appending: for (auto & p: st) res.append(p.first, p.second)

Array:
Contains Duplicate: Just use unordered_set ffs. JESUS CHRIST
Two Sum: Use unordered_map as inserting nums[i], if m.count(target - nums[i])
appear in map, we found a solution O(n), O(n)
Using two pointer make it O(n), O(1).

Maximum Sum Subarray: Single loop, 2 global var: maxSum and cur. If we come up a
new number, curSum = max(curSum +nums[i], nums[i]), then compare maxSum =
max(curSum, maxSum). The idea is: Once we come up to a number, see if we want to
add it, or we want to start over at that number. The checkpoint is a negative value

Maximum Product Subarray: Same idea as maximum sum subarray. But we have another
check: 0. 0 turns separate arrays into chunks. negative value flips the minimum to
maximum. So we need to keep check of curMin as well. Single loop, keep track of 3
global var: maxSum, curMax, curMin.
- tmp = curMax (we store this for curMin calculation, since curMax change)
- curMax = max({nums[i], nums[i]*curMax, nums[i]*curMin})
- curMin = min({nums[i], nums[i]*tmp, nums[i]*curMin})
- maxSum = max({maxSum, curMax, curMin}) // THen return maxSum in the end of
function.

Subsets I (Leetcode 78): [] [1] -> [] [1] [] [1] -> [] [1] [2] [1,2]. So the
algorithm is nested loop. Outer loop keep track of new element (nums[i]). Inner
loop do 2 things: mimic & double the res size, add new element to the half (mimic)
size of the res. Repeat.
Subsets II: the formula: j = repeatCount/(repeatCount+1). This start the new mimic
portion, works for 0
[1,2,2]: [] [1] [2] [1,2] -> [] [1] [2] [1,2] [2] [1,2] -> [] [1] [2] [1,2]
[2,2] [1,2]
[1,2,2]: [] [1] [2] [1,2] [2,2] [1,2] -> [] [1] [2] [1,2] [2,2] [1,2] [2,2]
[1,2] -> [] [1] [2] [1,2] [2,2] [1,2] [2,2,2] [1,2,2,2]

Move Zeroes: Give array, move all 0s to the right, keep everything in order
-> Solution: Partitionning algorithm (usually used in quick sort, ..) (MUST
KNOW THIS)
- Initialize left = 0; then make a forloop i from 0 to container.size()
- If the condition of the left side satisfies, swapValue(left, i), then left+
+
-> Solution 2: Smart ass but simple
- Record index of last time we see a non-zero: lastIndex
- Loop from i to container.size, if see non-zero, swap(nums[i],
nums[lastIndex]), lastIndex++;
- Later on, loop again from lastIndex to end, fills with 0s.

723. Candy Crush:


-> O((RxC)^2)
- 2 loop to get every single square. Find matching here, change it to negative
numbers (visited)
- Drop down: Do partition algorithm, 1 left pointer + 1 for loop. Swap left vs
currentIndex if number > 0

Linked List:
Reverse Linked List: Just becareful with operations. Use pre, head and cur.
Reassign head at the end. O(n), 1

QUEUE:
994. Rotting Oranges: Multi source BFS. Initialize level = 0. Remember: Inside
while (!q.empty()), save q.size() first before iterating thorugh level. q.pop() &
q.front() inside for loop that is inside while loop. Near the end of while loop,
check if current queue size: q.size() > 0, increase level.

Maximum Sliding Window:


- Sol1: priority queue, code short & simple, but O(NlogN)
- Sol2: deque, more complex but O(N). Monotonic queue problem, queue always
store decreasing order. Front is always maximum. After every loop, pop front. If
encounter greater element than front, pop everything.

Graph:
Number of Island: Loop each index of 2d-array, use BFS on an island, mark visited
(either in place or new array). O(m.n), O(m.n)

Binary:
Reverse Bits: Tricks: Get the ith digits: digit = n>>i & 1; adding digits to the
end: a*2 + digit; or a<<1 + digit. O(n)
Missing numbers: Trick: XOR same number gets 0, XOR 0 with a number get a number.
So XOR everything together, meaning nums[i] ^ i (i from 1 to n) then XOR res^n give
you the result. Other solution is just do n(n+1)/2 - sum(nums[i from 0 to size]) =
res.

Matrix:
Rotate Image:
Method 1: Do spiral interval, shift a row to column, store the placement
value first though.
Method 2: Do a transpose, then do a reverse (horizontally or vertically)
depends on flip 90 clockwise or cc.

Recursion:
Merge Sort: Divide array by 2, base case is array size = 1, then merge the two sub-
array.

93. Restore IP address: Recursion exhaustive search.

Tree:
Invert Binary tree: DFS, change left to right, recursive root->left, recursive
root->right, return root

K-smallest element in BST: , k global (by reference), when k == 0, save Res global.

When done, return res. Modify the function call to pass by reference.

Maximum Depth of Binary Tree: return 1 + max(maxDepth(left), maxDepth(right))

Same Tree: if (!p & q) || (!q && p) return false; if (!p && !q) return true;
else return p->val == q->val && isSameTree(p->left, q->left) && isSameTree(p-
>right, q-right)
Subtree of Another Tree:
O(NxM): traverse O(N), check for everynode isSametree O(M). O(NxM)

Binary Tree Level Order Traversal: Queue


Binary Tree zigzag Print: Push to queue, pop from queue to stack, then print.

Trie (Prefix Tree):


- Constructor (Root, children[26], isEndOfWord)
- Insert(Node*root,string word): Loop through word, if (!cur-
>children[indexWord]) construct word, else cur = cur-
>children[indexWord]. At the end, cur->isEndOfWord = true
- searchWord(Node*root,string word): Loop through word, if (!cur-
>children[indexWord]) return false, else cur = cur->children[indexWord]. At
the end, return cur && cur->isEndOfWord

Construct Binary Tree from Preorder & Inorder:


// Key idea: Root is always first in preorder, find the subleft, subright in
both preorder and inorder array, then do recursive call to construct root->left &
root->right.
-> Elegance solution O(N^2):
// first we find root in inorder, call it mid
// Then construct arrays: subarrayPreLeft, subarrayPreRight, subarrayInLeft,
subArrayInRight
// Then construct root->left = buildTree(subarrayPreLeft, subarrayPreRight),
same for root->right
// Then return root.
-> Efficient solution O(N): (A LOT OF indexing and then recursive)
// Root is always first in preorder, find the subleft, subright in both
preorder and inorder array
// First, find index of root in inorder, call it mid
// Then divide subleft and subright (in preoreder and inorder) correctly based
on that index:
// preLeft start at: preLeft + 1, ends at preLeft + mid - inLeft;
// inLeft start at: inLeft, ends at mid - 1;
// preRight start at: preLeft + mid - inLeft + 1;
// inRight start at: mid + 1, ends at inRight;
// Then call root->left = helper(preorder, inorder, preSubLeftIndex,
preSubRightIndex, inSubLeftIndex, inSubRightIndex) and root->right ... accordingly

98. Valid Binary Search Tree:


- Iterative: In order traversal. The output is sorted increasing
- Recursion: Keep track of minNode & maxNode, compare root only, very simple
- If minNode > root->val, return false. If maxNode < root->val, return
false;
- If traverse left, maxNode = root, minNode = minNode
- If traverse right, minNode = root, maxNode = maxNode

BackTrack
79. Word Search:
-> O(R*C * 4*(3^L)) dfs backtrack solution. R=row, C=col, L=word.length().
3^L b/c we dont go back to visited node. 4*(3^L) because 4 directions.
- For(rows) for(cols), if (dfs(board, word, rows, col, 0)) return true
// Sub problem start at 0 index of word.
- If (pos == word.size()) return true; // Base case, found match
- If out of bound, return false; // Out of Bound
- If (board[row][col] != word[pos]) return false; // We dfs but at this
point there's no matching word
- else we OR the result of dfs(4directions) to bool furtherSearch search
while marking current one visited.
- At the end, mark current one back to original: board[row][col] = word[pos];
then return furtherSearch;

1415. The k-th Lexicographical String of All Happy Strings of Length n:


-> O(n*k): dfs backtrack + early terminate
- Maintain current string (for push, pop), global res for return, global
count to keep track of recursion
- If n == 0, if count == 0, res = cur, return;
- Loop through wordList = {a, b, c} except for value s.back()
- cur.push_back(wordList[i]); helper(n-1,count,cur,res); cur.pop_back()
//push at begin, pop at end

91. Decode Ways:


-> O(2^N): decision tree of 2 branch, taking 1 digit or 2 digits
- int backtrack(p, string& s)
- base case: index p = s.size , return 1(finish a string, add 1 to
count)
- base case: s[p] = '0' , return 0 (Can't decode starting with 0)
- int res = backtrack(p+1,s)
- if (taking 2 digits is valid), res += backtrack(p+2,s)
return res;

DP:
55. Jump Game I:
-> O(N^N): if pos == nums.size() - 1, flag = true. For (i in len), dfs(nums,
pos+i).
->
-> // O(N) greedy solution:
// Calculate from the end. If the i^th position can reach the goal, update
goal.
// Return goal == 0 // This means we can reach the final destination from
the beginning

You might also like