- I hate dynamic programming
- Bottoms up approach
- Calculate the values from the end result
- Since we can only climb 1 or 2 steps at a time, we'll start the base case at the start.
- [0, 0, 0, 0, 1, 1]
- 0 1 2 3 4 5
- From the end, it takes 1 action to get to the end of the staircase
- From the 3rd step, we can either take 1 step and end up at 4, or take 2 steps and end up at 5
- Since we already know how many ways it takes to get from 4 and 5 to the top
- We can add those two values and assign it to 3
- From 3, we can either take one or two steps
- [0, 0, 0, 0, 1, 1]
- 0 1 2 3 4 5
-
^ one two - temp = one
- one = one + two
- two = one
- From 2, we can either take one or two steps
- [0, 0, 0, 2, 1, 1]
- 0 1 2 3 4 5
-
^ one two - From 1, we can either take one or two steps
- [0, 0, 3, 2, 1, 1]
- 0 1 2 3 4 5
-
^ one two - Return one as it ends at the start of the stairs
- Bottoms up bottoms up
- We append a 0 to the end of the min cost since having 2 steps from the 2nd last position shouldn't incur costs
- This also avoids index out of range
- We start from len(n) - 1 ( - 2) and increment downwards
- [ a, b, c, d, e, 0]
-
^ one two - From d, we get the minimum of (e, 0) which is the same as saying taking one or two steps but choosing the cheapest
- Add that onto the cost of d
- Then return the minimum of starting at [0] or [1]
- Bottoms Up
- Append a 0 at the end, so that we can calculate without worrying about index
- [ a, b, c, d, e, 0 ]
-
^ r1 r2 - If we rob d we can't rob r1 = n + 1, but we rob d + r2 = n + 2
- The decision to rob at d at index i is
- Get the max between robbing d and not robbing d
- nums[i] = max(nums[i] + nums[i + 2], nums[i + 1])
- Just like climbing stairs, return max of nums[0] and nums[1]
- The same solution as the previous
- Need to check for empty array
- Need to check for singular entry
- The trick is to call House Robber one on [1:] and [:-1]
- The restrictions basically form a cycle array
- If we do the first element, we cant do the last
- If we do the last element, we cant do the first
- Therefore we just exclude these elements in consideration
- Keep track of the index of the longest substring instead of the substring itself
- Start the palindrome calculation from every letter
- For every letter
- Check for an odd palindrome by starting l and r from i
- Check for an even palindrome by starting l from i and r from i + 1
- Make sure to boundary check
- Check if length of r - l is more than the max index
- Return spliced array at res_l res_r + 1
- The same as longest palindromic substring
- The if statement for a palindrome extends to the whole loop
- Every iteration of the loop means an additional substring is added
- Keep track of the amount in self.res
- Bottoms Up
- But instead of doing "steps" we're either considering numbers as 1 digits or 2 digits
- Hashmap for the dp. Base case of len(s) = 1
- Loop every digit from bottom up
- If == 0, we assign it as 0 mappings as this depends on whether the next number exists or not
- Then we treat it as a single digit/step, we add onto d[i + 1]
- Since our base case is len(s) = 1, the first iteration will assign the single case letter as 1
- The double case layers as a seperate if on single case
- We can only double if i + 1 < len(s)
- Check that i is either 1 or 2, if 2 then check if its 0-6
- Then since this is "two" steps, we add onto d[i + 2]
- Not bottoms up... I forgot the name of it
- Initialise dp array
- [0] initial index, and inf * amt of coins to the target number
- The dp array will store "the amount of coins it takes to get to that index
- Each index is a coin amount
- Therefore at index 5, we will get the minimum amount of coins that sum to $5
- Loop through amount + 1 (since first element is appended to 0)
- For each coin, check if the sum of the current coin - the possible coins <= 0
- Perform Dp operation
- dp[i] = min(dp[i] (previous amount), dp[i - coin] + 1 (the amount to get to the previous sum + 1 for the current coin))
- Check if inf propagated to the end of the array, if so return - 1
- Return dp[-1]
-
Sliding window esque dp solution
-
Keep track of res
- Initialise as max(nums) as the subarray could be size 1
-
CurMin and CurMax
-
Loop through all nums and calculate the curMax and curMin with max and min operations
- n * curMin, n * curMax and n
- Use temp variable to store old curMax
-
res = max(res, curMax)
-
This works because the n basically moves the subarray up once we find a better subarray
-
Storing curMin means that we can find a case for -ve n
-
The iterative solution
-
Observations about negative numbers
- Even negative numbers in array means the whole array is the maximal subarray
- Odd negative numbers means that we have to exclude one of the negative numbers
- We can do that by taking the subarrays to the left and right of the number
-
We can then know that for some number k we can take the 0 to k - 1 subarray and the k + 1 - n subarray
-
Since we don't know where this value is, we can do two passes, keeping track of the max value
-
Because we have a case where 0 could be in the array, we can reset the product of the pass to 1.
- Word set of the dict
- Initialise dp to [False] * n + 1
- Since it's bottoms up, initialise dp[n] to True
- Loop -ve range n - 1
- We loop through j = i + 1 to n + 1 (this is why we needed dp to be n + 1)
- The current characters were trying to get is i:j
- The previous computed values are at dp[j]
- If i:j is a valid word and dp[j] which is the rest of the array is a valid break
- Then the array up to dp[i] is a valid break
- Break out of the j loop since we've found a match for this index i
- As per usual, return dp[0] for bottoms up
- Initialise dp [1] * len
- Not bottoms up
- For i in nums
- For j in i, for every number between 0 - the current index
- Find the longest increasing subsequence where nums[i] > nums[j] (strictly increasing)
- When this is false, we assign dp[i] = max dp[i] and dp[j] + 1 since j will start from 0 and build the subsequence up to j
- This is getting the maximum between the LIS that ends at dp[i] and the LIS at dp[j] + 1 including the current value
- We continue doing from k - i since there might be an even longer subsequence than from 0 - k
- Return max(dp) since we arent keeping track of max in a res (slows down time too much)
- 2 approaches
- BFS with queue
- Initialise every index on the matrix
- If 0, add to queue
- Otherwise, mark as -1 to indicate unvisited
- While the queue isn't empty
- Pop from queue (first loop is starting from 0)
- For each direction
- Check for boundaries and check that this current location IS -1 (not visited)
- Assign the direction with the origin position + 1
- Append this position to the queue
- Initialise every index on the matrix
- Dynamic Programming
- Only process the 1 cells
- Since we can't dp on all 4 directions at a time due to not knowing if it was computed yet
- We restrict from top-left to bottom-right and bottom-right to top-left
- That means on the first pass, we calculate distance from the top and left adjacent cells + 1
- On the second pass, we calculate distance from the bottom + 1 and right + 1 adjactent cells and get minimum compared to the first pass
-
Initialise dp array m * n with 1
-
for m, then for n starting from 1
- i, j is the sum of i - 1, j and i, j - 1
-
Return the end value
-
Draw out the cell table
-
All the cells on the bottom and right side edges have only 1 valid path to go to the end
-
Starting from the end (bottom right) if we look at a smaller 2x2 square, the amount of paths it can take is 2 (down, right and right, down) which is also the sum of the edges
- (DFS)
- Therefore the unique paths can be built from the previous i + 1, j and i, j + 1
- If we dfs, base case where
- i or j is not in range -> return 0
- i = m - 1 and j = n - 1 respectively (0 indexed)
- then return the dfs(i + 1, j) + dfs(i, j + 1)
- The other solution is the Sliding Window solution
- Initialise maxleft and maxright arrays of size n
- Starting from +1 because there is no maxleft of the leftmost
- Compute the maxleft of i as the max of the height of the directly left bar at height[i - 1] and the maximum of the previously computed max bar at maxleft[i - 1]
- Starting from n - 2 becuase there is no maxright of the rightmost
- Same logic but just + 1
- For each bar i in range len height
- The minimum level is between maxLeft and maxRight
- If the level is larger than the current bar height, forming a dip
- Add to the total