LC Blind 75 Flashcards
Two Sum
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
Naive Solution: cycle through list for each element and identify the indices of the target values
Optimal Solution: Create dict with [key, value] as [value, index] and check for target - value as a key. If in the dict, return values, if not then add to the dict
Best Time to Buy and Sell Stock
You are given an array prices where prices[i] is the price of a given stock on the ith day.
You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.
Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.
Initialize currMin and currMax
Check if current delta with Min is > Max
check if value < min and reset if necessary
Consider Kadane’s Algorithm for max subarray problem in general
Climbing Stairs
You are climbing a staircase. It takes n steps to reach the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Fibonacci Number
Each step can be reached from two places - step (n-1) and step (n-2). To calculate each step’s possible outcomes one must calculate the prior two steps the whole way.
Contains Duplicate
Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct.
- Loop through array, check if element in set. Return if true, add if not
- compare length of array to set of array. Duplicates will result in a reduced size for the set
Set Matrix Zeroes
Given an m x n integer matrix matrix, if an element is 0, set its entire row and column to 0’s, and return the matrix.
You must do it in place.
Optimal Speed Solution using O(m+n) space:
- Set array for row and for column equal to length of appropriate dimension
- iterate through whole array checking for zeroes. If detected, set appropriate row and col marker to 0.
- Run through array again, setting any values that match the row or col 0 markers to be 0.
To make this O(1) space:
use the first row and column of the array as the markers
Longest Substring Without Repeating Characters
Given a string s, find the length of the longest substring without repeating characters.
Sliding Window Technique
- If s[r] has not been seen, increment the output.
- If s[r] has been seen, but the value is less than the left marker, increment the output
- If s[r] has been seen, but the value is greater than the left marker, move the left marker to the index past where it was seen
- increment/set the index for the right marker in seen
Maximum Depth of Binary Tree
Given the root of a binary tree, return its maximum depth.
A binary tree’s maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
Recursively check each layer, looking for leaf nodes. At leaf nodes return (1).
Anywhere the node splits, return the max of the helper function while adding 1 each layer.
Only edge case is empty tree, return 0.
House Robber
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
- Check base conditions: array fewer than 3 values and compare first two values.
- Each step, we will iterate the array and rewrite the value with the optimal value at this point in the array. We will compare the previous value with the sum of the current and n-2 values.
- After one iteration, we can return the final value
Reverse a Linked List
Given the head of a singly linked list, reverse the list, and return the reversed list.
- Set base conditions: check for empty node
- Define required variables: prev and curr to track reverse and forward linked list respectively. Set prev.next to be None.
- while curr is not empty, set the next values as a temp variable. Then redirect the current node to prev (the reverse node. Then set prev to be curr (the reversed list including the most recent node). Then reset curr to be the next node we had set aside at the beginning.
- These steps will repeat, reversing the list one step at a time. Return the reversed list (prev).
Product of Array Except Self
Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].
The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.
You must write an algorithm that runs in O(n) time and without using the division operation.
The trivial solution to this is to use the division operator, but that is one of the conditions listed. So we will make a two pass solution.
Pass 1: we will fill our output array with the product of each number leading up to that point, but not including that index.
Pass 2: we will do the same, but in reverse. This results in creating an output array that has multiplied all values together and managed to skip the value at each index.
Longest Repeating Character Replacement
You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times.
Return the length of the longest substring containing the same letter you can get after performing the above operations.
Declare max length, max count, and count (dict).
Much like longest subsequence, we will be iterating and checking at each iteration if we’re at a new best or not.
First, we will increment the dict entry for the next character of the string.
Then we will check the max count as the max against itself and the count at the current character.
max length will always be k + max count. This is because whatever the max count in a range is, we can add k to that for our max length. If max length is less than k + max count, increment max length (it should never increment by more than one).
If max length did not grow, then we must contract the window from the back, decrement the character at max length distance from the front of the window.
This will repeat and is very similar to Kadane’s algorithm. We will return max length
Minimum Window Substring
Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string “”.
The testcases will be generated such that the answer is unique.
A substring is a contiguous sequence of characters within the string.
Pieces to account for:
- Hash table to store needed char frequency (collections.Counter)
- Total characters needed (missing = len(t))
- Start and End initialized to 0
- Iterator i initialized to 0 (to account for left side window)
We will do a sliding window over the enumerate (s, 1)
Each step we will do the following
- Check if the char’s hash is greater than 0. If so, decrement missing by 1 and decrement the character’s hash
- If missing == 0, then all values have been located in the substring.
- If missing == 0, we will start sliding i/left forward until we find the true start of this substring. After we find the true substring, we will proceed with previous steps or increment i
Coin Change
You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.
Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
You may assume that you have an infinite number of each kind of coin.
Dynamic Programming Solution
Begin by initializing the dp array, which is [0] + [amount + 1 for n in amount]. We will be checking the best solution for each value from 1 to amount.
Next, we will start a nested loop. The outer loop holding the coins, the inner loop ranging from (coin, amount). The inner loop will compare to find the min at each step comparing dp[i] and dp[i - coin] + 1. This is because we want whatever is lower of using this coin, and using the coin implies the latter. The former suggests that a previous denomination had a more optimal result and we will use that for now.
We will return the last value of the array IFF it is >= amount. Otherwise return -1.
Same Tree
Given the roots of two binary trees p and q, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.
Recursive Solution:
Each step we want to check that the two tree values being compared are 1. not null, and 2. the same.
If p and q, then we will return the result of the vals of p and q, and the recursive step for left and right.
To account for Null/Null case, we will return p is q after this step to close the recursive step
Invert Binary Tree
Given the root of a binary tree, invert the tree, and return its root.
We will be recursively stepping through the tree, each time flipping the left and right children and then calling the invert function on the left and right children respectively.
Detect Cycle in a Linked List
Given head, the head of a linked list, determine if the linked list has a cycle in it.
There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail’s next pointer is connected to. Note that pos is not passed as a parameter.
Return true if there is a cycle in the linked list. Otherwise, return false.
The method we will be using is two pointers, one fast and one slow.
First we must check if the head is null and initialize the fast pointer (we will be using the head as the slow pointer).
Then while the fast and fast.next are valid, we will continue to loop through and increment the slow pointer (by one) and fast pointer (by two).
If there is a cycle, the fast pointer will “catch up” to the slow pointer and eventually equal it. If there is no cycle, then we will reach the end of the linked list.
Clone Graph
Given a reference of a node in a connected undirected graph.
Return a deep copy (clone) of the graph.
Each node in the graph contains a value (int) and a list (List[Node]) of its neighbors.
Test case format:
For simplicity, each node’s value is the same as the node’s index (1-indexed). For example, the first node with val == 1, the second node with val == 2, and so on. The graph is represented in the test case using an adjacency list.
An adjacency list is a collection of unordered lists used to represent a finite graph. Each list describes the set of neighbors of a node in the graph.
The given node will always be the first node with val = 1. You must return the copy of the given node as a reference to the cloned graph.
We will be approaching with iterative DFS approach.
- First we must check the edge case of an empty graph and return
- Next we must define the necessary pieces: nodeCopy (initialized instance of Node with empty neighbors), dic ({node: nodeCopy}), and stack (our iteration mechanic).
- While stack is not empty we will pop values off (neighbor) and then iterate through each neighbor.
- If we have not seen a neighbor before, we must establish an instance of the node (Node(neighbor.val, [])). This will be neighborCopy
4a. Then we must set the dic[neighbor] to neighborCopy.
4b. Next we will append neighborCopy to dic[Node].neighbors
4c. Last we will append neighbor to stack - If we have seen the neighbor before, we will just append dic[neighbor] to dic[node].neighbors
- return nodeCopy
Maximum Subarray
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
A subarray is a contiguous part of an array.
We will be creating a dynamic programming approach
- initialize current and max sum variables
- iterate througheach num in nums from 1 to the end
- at each step, set the current to the max of the current + num and the num. This will reset the count if any individual num is greater than the highest total before it.
- set max to the max of current and max
- return max
Maximum Product Subarray
Given an integer array nums, find a contiguous non-empty subarray within the array that has the largest product, and return the product.
It is guaranteed that the answer will fit in a 32-bit integer.
A subarray is a contiguous subsequence of the array.
Similar to Maximum Subarray - we will be performing a dynamic programming solution. The added complexity is accounting for polarity flip that negative values cause
- initialize values for positive and negative products, as well as the answer all to the first value of nums
- iterate through each values of nums[1:]
- At each step, we will recalculate the positive and negative products by taking the respective max and min of the newly added pieces (e.g. max(num, posProd * num, negProd * num). These must be assigned to temporary variables at first so that values aren’t corrupted
- replace the values for the positive and negative products and compare the answer for max
- return max
Find Minimum in Rotated Sorted Array
Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:
[4,5,6,7,0,1,2] if it was rotated 4 times. [0,1,2,4,5,6,7] if it was rotated 7 times.
Notice that rotating an array [a[0], a[1], a[2], …, a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], …, a[n-2]].
Given the sorted rotated array nums of unique elements, return the minimum element of this array.
You must write an algorithm that runs in O(log n) time.
We will be doing a modified binary search to find the minimum in the array.
- initialize left and right to the start and end of the array
- begin a while loop that persists while left < right
- each loop, we will set mid to be the midpoint of left and right (left + right) // 2.
- Next we will assess the current state of the binary search. if the nums of midpoint is greater than nums of right, then the minimum is somewhere on the right and we must adjust the left barrier accordingly (left = mid + 1). Otherwise, we must adjust the right barrier (right = mid).
- In the end, the contents of nums[left] will be the min and we will return that
Search in Rotated Sorted Array
There is an integer array nums sorted in ascending order (with distinct values).
Prior to being passed to your function, nums is possibly rotated at an unknown pivot index k (1 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].
Given the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.
You must write an algorithm with O(log n) runtime complexity.
We will be doing a modified binary search to find the target element in the array.
- First we must initialize left and right as 0 and the last index
- Next we will enter a while loop that persists as long as left <= right.
- Each iteration of this loop, we will calculate the midpoint between left and right (left + right) // 2 and check if the value of the midpoint is the target and return.
- Then we will have a two tier if statement that will:
4a. In the first tier check if the array is rotated left or right. We determine this based on the result of comparing the mid point to the left point (if midpoint greater, left rotated, else right rotated).
4b. In the second tier we will determine how to set the next window. First we will check if the target is between left and mid or mid and right (depending on step 4a). If so, we decrement/increment the right/left value to adjust the window appropriately. - Ultimately, the window will keep adjusting until the value is found (and will be returned), or the value will not exist (and the loop will end and we return -1)
Notes: The premise of this problem is on assessing the direction and narrowing from the 4 possible outcomes (left/right + left/right)
Three Sum
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
Notice that the solution set must not contain duplicate triplets.
We will be doing a modified sliding window technique to solve this problem.
- First we must sort the array. This is very important because our solution will be O(n*n) and sorting is O(nlogn) and therefore will not impact the speed while allowing us to take a more systematic approach to the problem.
- Next, we will initialize some variables. Specifically a solution array to hold any resulting triplets, and also a variable N representing the length of the array
- We will start iterating through the array from the beginning. Each step, we must first check to make sure that our current value is not the same as the previous value. If so, continue. Otherwise, calculate the “target” which will be the negative value at nums[i] and set the left and right window indices (i + 1, N - 1)
- Now for the crux of the solution. For each position, we will be starting at the positions immediately following the current position and the end of the array.
- Next we will compare the sum of the 3 values (i, l, r) and if l + r = target, then we will add the triplet. After this we increment l. Care must be taken to guarantee no duplicates, and we must set another while loop to check that the new value of l is different from the previous l value.
- If l + r > target, this means we need to reduce our value and therefore will shift our right value (ceiling) lower (r - 1).
- Otherwise, l + r < target. This means that we need to increase the floor (l + 1)
- After completing the iteration, we will return the array of triplets
Container With Most Water
Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.
Notice that you may not slant the container.
We will be using a dp solution
- First we must declare L, R, width, and res : 0, len - 1, len - 1, 0
- Next we will iterate backwards from width to 0
- At each step, we must check if L < R. Whichever is smaller will be the variable we manipulate for the current step.
- We will alter both res and the smaller of L/R. res will be the max of res and height[X] * width. L/R will be increment or decremented. This will progressively compare the shrinking zone with the previous maximum.
- return the result
Longest Increasing Subsequence
Given an integer array nums, return the length of the longest strictly increasing subsequence.
A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].
DP + Greedy Binary Search
- First we will declare an empty list to hold our results
- Next, we will iterate through each element in the nums array as x.
- For each value x we will:
3a. Check if the results list is empty or if x is greater than the last element in the results list. If this is the case, we will append x to the results list.
3b. Otherwise, we will do a binary search in the results list for the smallest number that is greater than or equal to x (using any method such as bisect_left()). - Next, we replace the value in the results list at the id calculated at step 3b.
- return the length of the results list.
This solution is based on the fact that we know we only need the length of the subsequence. This means that as we get new values we may overwrite values in our results list that will result in a potentially “wrong” set of values, but that doesn’t matter because the length has been recorded.
This allows for any number of new iterations of longer subsequences to regenerate using the same framework.
This solution is O(nlogn) time and O(n) space but can be improved to O(1).