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?
Example 1:
Input: n = 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 stepsExample 2:
Input: n = 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 stepThe number of ways to reach the nth step is the sum of the number of ways to reach the (n-1)th step and the (n-2)th step. This is because we can either take a single step from (n-1) to n or a double step from (n-2) to n.
This approach resembles the Fibonacci sequence where each number is the sum of the two preceding ones.
-
Base Cases:
- If
nis 1, there's only one way to climb the staircase: taking a single step. - If
nis 2, there are two ways to climb the staircase: (1 step + 1 step) or (2 steps).
- If
-
Initialization:
- We initialize two variables,
oneandtwo, both set to 1. These represent the number of ways to reach the first step and the second step, respectively.
- We initialize two variables,
-
Iterative Calculation:
- We use a loop to iterate from the 3rd step up to the nth step.
- In each iteration, we update the
oneandtwovariables.oneis updated to the sum ofoneandtwo(the number of ways to reach the current step), andtwois updated to the old value ofone.
-
Result:
- After completing the loop,
onecontains the number of distinct ways to climb to the nth step.
- After completing the loop,
We need to find the number of distinct ways to climb a staircase with 5 steps, where each step can be either 1 step or 2 steps at a time.
We start with two variables:
one = 1: This represents the number of ways to reach the zero'th step.two = 1: This represents the number of ways to reach the first step.
We will use a loop to update these variables until we reach the 5th step.
-
Step 3:
- Current state:
one = 1,two = 1 - Calculation:
one = one + two(number of ways to reach the 2nd step) one = 1 + 1 = 2- Update:
twois now the old value ofone two = 1- New state:
one = 2,two = 1
- Current state:
-
Step 4:
- Current state:
one = 2,two = 1 - Calculation:
one = one + two(number of ways to reach the 3rd step) one = 2 + 1 = 3- Update:
twois now the old value ofone two = 2- New state:
one = 3,two = 2
- Current state:
-
Step 5:
- Current state:
one = 3,two = 2 - Calculation:
one = one + two(number of ways to reach the 4th step) one = 3 + 2 = 5- Update:
twois now the old value ofone two = 3- New state:
one = 5,two = 3
- Current state:
-
Step 6:
- Current state:
one = 5,two = 3 - Calculation:
one = one + two(number of ways to reach the 5th step) one = 5 + 3 = 8- Update:
twois now the old value ofone two = 5- New state:
one = 8,two = 5
- Current state:
After the loop completes, the variable one contains the number of distinct ways to reach the 5th step, which is 8.
Time Complexity:
- The time complexity is
$O(n)$ because we use a single loop that runs from 1 to$n-1$ .
Space Complexity:
- The space complexity is
$O(1)$ because we only use a fixed amount of space (two variables,oneandtwo), regardless of the input size$n$ .
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.
You are given an integer array nums where nums[i] represents the amount of money the ith house has. The houses are arranged in a straight line, i.e. the ith house is the neighbor of the (i-1)th and (i+1)th house.
Return the maximum amount of money you can rob without alerting the police.
Example 1:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.Example 2:
Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.-
Approach:
- Use two variables,
rob1androb2, to keep track of the maximum amount of money that can be robbed up to the previous house and the house before the previous house, respectively. - Iterate through each house and determine whether to rob the current house or skip it.
- Use two variables,
-
Dynamic Programming Transition:
- For each house
i, we have two choices:- Rob the current house and add its money to
rob1(the amount robbed up to the house before the previous house). - Skip the current house and carry forward
rob2(the amount robbed up to the previous house).
- Rob the current house and add its money to
- Update
rob2to be the maximum of these two choices.
- For each house
Let's walk through the example nums = [2,7,9,3,1] step by step:
-
Initialization:
rob1 = 0,rob2 = 0
-
House 1 (Amount = 2):
newRob = max(2 + 0, 0) = 2- Update
rob1 = rob2 = 0 - Update
rob2 = newRob = 2
-
House 2 (Amount = 7):
newRob = max(7 + 0, 2) = 7- Update
rob1 = rob2 = 2 - Update
rob2 = newRob = 7
-
House 3 (Amount = 9):
newRob = max(9 + 2, 7) = 11- Update
rob1 = rob2 = 7 - Update
rob2 = newRob = 11
-
House 4 (Amount = 3):
newRob = max(3 + 7, 11) = 11- Update
rob1 = rob2 = 11 - Update
rob2 = newRob = 11
-
House 5 (Amount = 1):
newRob = max(1 + 11, 11) = 12- Update
rob1 = rob2 = 11 - Update
rob2 = newRob = 12
The maximum amount of money that can be robbed without alerting the police is 12.
-
Time Complexity:
$O(n)$ , wherenis the number of houses. We iterate through the list of houses once. -
Space Complexity:
$O(1)$ , as we only use a constant amount of space forrob1androb2.
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night.
You are given an integer array nums where nums[i] represents the amount of money the ith house has. The houses are arranged in a circle, i.e. the first house and the last house are neighbors.
Return the maximum amount of money you can rob without alerting the police.
Example 1:
Input: nums = [2,3,2]
Output: 3
Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), because they are adjacent houses.Example 2:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.Example 3:
Input: nums = [1,2,3]
Output: 3The problem is an extension of the "House Robber I" problem with an additional constraint that the houses are arranged in a circle. This means we cannot rob both the first and last houses simultaneously.
- Approach:
- I've split the problem into two subproblems:
- Rob houses from the first house to the second-last house.
- Rob houses from the second house to the last house.
- The reason I've split the problem this way is to avoid the situation where both the first and last houses are robbed.
- The final solution is the maximum of these two subproblems.
- I've split the problem into two subproblems:
Let's walk through the example nums = [2, 3, 2] step by step:
-
Initialization:
- We need to consider two cases:
- Case 1: Rob houses from the first house to the second-last house:
nums[:-1] = [2, 3] - Case 2: Rob houses from the second house to the last house:
nums[1:] = [3, 2]
- Case 1: Rob houses from the first house to the second-last house:
- We need to consider two cases:
-
Case 1 (
nums = [2, 3]):- Initialize
rob1 = 0,rob2 = 0 - House 1 (Amount = 2):
newRob = max(0 + 2, 0) = 2- Update
rob1 = 0,rob2 = 2
- House 2 (Amount = 3):
newRob = max(0 + 3, 2) = 3- Update
rob1 = 2,rob2 = 3
- Maximum for this case:
3
- Initialize
-
Case 2 (
nums = [3, 2]):- Initialize
rob1 = 0,rob2 = 0 - House 1 (Amount = 3):
newRob = max(0 + 3, 0) = 3- Update
rob1 = 0,rob2 = 3
- House 2 (Amount = 2):
newRob = max(0 + 2, 3) = 3- Update
rob1 = 3,rob2 = 3
- Maximum for this case:
3
- Initialize
The maximum amount of money that can be robbed without alerting the police is the maximum of the two cases: max(3, 3) = 3.
-
Time Complexity:
$O(n)$ , wherenis the number of houses. We iterate through the list of houses twice (once for each subproblem). -
Space Complexity:
$O(1)$ , as we only use a constant amount of space forrob1androb2.
Given a string s, return the longest substring of s that is a palindrome.
A palindrome is a string that reads the same forward and backward.
If there are multiple palindromic substrings that have the same length, return any one of them.
Example 1:
Input: s = "babad"
Output: "bab"
Explanation: "aba" is also a valid answer.Example 2:
Input: s = "cbbd"
Output: "bb"To solve the problem of finding the longest palindromic substring, I've used a two-pointer approach to expand around the center.
-
Approach:
- For each character in the string, consider it as the center of a potential palindrome.
- Expand outwards from the center and check for the longest palindrome.
- We need to consider both odd-length and even-length palindromes.
-
Helper Function:
- We create a helper function
checkPalindromethat takes two pointersleftandright, and expands outwards as long as the characters at these pointers are the same. - When the characters at
leftandrightare no longer the same, the function returns the substring betweenleft + 1andright.
- We create a helper function
-
Main Function:
- Initialize an empty string
resStringto store the longest palindrome found. - Iterate through each character in the string:
- For each character, use it as the center for an odd-length palindrome and an even-length palindrome by calling
checkPalindrome. - Update
resStringif a longer palindrome is found.
- For each character, use it as the center for an odd-length palindrome and an even-length palindrome by calling
- Initialize an empty string
-
Clarification on Odd and Even Length Palindromes:
- Odd-Length Palindromes:
- We start with the same index for both left and right, i.e.,
left = iandright = i. - For example, starting at index 0, we would have
left = 0andright = 0. - As we expand, we decrement left by 1 and increment right by 1, creating palindromes of length 3, 5, 7, and so on.
- We start with the same index for both left and right, i.e.,
- Even-Length Palindromes:
- We start with adjacent indices for
leftandright, i.e.,left = iandright = i + 1. - For example, starting at index 0, we would have
left = 0andright = 1. - As we expand, we decrement left by 1 and increment right by 1, creating palindromes of length 2, 4, 6, 8, and so on.
- We start with adjacent indices for
- Odd-Length Palindromes:
Let's walk through the example s = "babad" step by step:
-
Initialization:
resString = ""
-
Iteration:
-
For
i = 0(Character 'b'):- Check odd-length palindrome centered at 'b':
"b" - Check even-length palindrome centered between 'b' and 'a':
"" - Update
resStringto"b"
- Check odd-length palindrome centered at 'b':
-
For
i = 1(Character 'a'):- Check odd-length palindrome centered at 'a':
"bab" - Check even-length palindrome centered between 'a' and 'b':
"" - Update
resStringto"bab"
- Check odd-length palindrome centered at 'a':
-
For
i = 2(Character 'b'):- Check odd-length palindrome centered at 'b':
"aba" - Check even-length palindrome centered between 'b' and 'a':
"" resStringremains"bab"
- Check odd-length palindrome centered at 'b':
-
For
i = 3(Character 'a'):- Check odd-length palindrome centered at 'a':
"a" - Check even-length palindrome centered between 'a' and 'd':
"" resStringremains"bab"
- Check odd-length palindrome centered at 'a':
-
For
i = 4(Character 'd'):- Check odd-length palindrome centered at 'd':
"d" - Check even-length palindrome centered after 'd':
"" resStringremains"bab"
- Check odd-length palindrome centered at 'd':
-
-
Time Complexity:
$O(n^2)$ , wherenis the length of the string. We expand around each center in the string, and in the worst case, each expansion can take up tonsteps. -
Space Complexity:
$O(1)$ , since we only use a constant amount of additional space for variables.
Given a string s, return the number of palindromic substrings in it.
A string is a palindrome when it reads the same backward as forward.
A substring is a contiguous sequence of characters within the string.
Example 1:
Input: s = "abc"
Output: 3
Explanation: Three palindromic strings: "a", "b", "c".
```bash
Example 2:
Input: s = "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".To solve the problem of counting palindromic substrings, I've used a two-pointer approach to expand around the center.
-
Approach:
- For each character in the string, consider it as the center of a potential palindrome.
- Expand outwards from the center and count all palindromes.
- We need to consider both odd-length and even-length palindromes.
-
Helper Function:
- We create a helper function
countPalindromethat takes two pointersleftandright, and expands outwards as long as the characters at these pointers are the same. - It returns the count of palindromic substrings found during the expansion.
- We create a helper function
-
Main Function:
- Initialize a variable
resto store the total count of palindromic substrings. - Iterate through each character in the string:
- For each character, use it as the center for an odd-length palindrome and an even-length palindrome by calling
countPalindrome. - Add the counts returned by
countPalindrometores.
- For each character, use it as the center for an odd-length palindrome and an even-length palindrome by calling
- Initialize a variable
-
Clarification on Odd and Even Length Palindromes:
- Odd-Length Palindromes:
- We start with the same index for both left and right, i.e.,
left = iandright = i. - For example, starting at index 0, we would have
left = 0andright = 0. - As we expand, we decrement
leftby 1 and incrementrightby 1, creating palindromes of length 1, 3, 5, and so on.
- We start with the same index for both left and right, i.e.,
- Even-Length Palindromes:
- We start with adjacent indices for left and right, i.e.,
left = iandright = i + 1. - For example, starting at index 0, we would have
left = 0andright = 1. - As we expand, we decrement
leftby 1 and incrementrightby 1, creating palindromes of length 2, 4, 6, and so on.
- We start with adjacent indices for left and right, i.e.,
- Odd-Length Palindromes:
Let's walk through the example s = "aaa" step by step:
-
Initialization:
res = 0
-
Iteration:
-
For
i = 0(Character 'a'):- Check odd-length palindrome centered at 'a':
left = 0,right = 0, count = 1 (palindrome:"a")
- Check even-length palindrome centered between 'a' and 'a':
left = 0,right = 1, count = 1 (palindrome:"aa")
- Update
resto2
- Check odd-length palindrome centered at 'a':
-
For
i = 1(Character 'a'):- Check odd-length palindrome centered at 'a':
left = 1,right = 1, count = 1 (palindrome:"a")left = 0,right = 2, count = 1 (palindrome:"aaa")
- Check even-length palindrome centered between 'a' and 'a':
left = 1,right = 2, count = 1 (palindrome:"aa")
- Update
resto5
- Check odd-length palindrome centered at 'a':
-
For
i = 2(Character 'a'):- Check odd-length palindrome centered at 'a':
left = 2,right = 2, count = 1 (palindrome:"a")
- Check even-length palindrome centered after 'a': No valid palindrome
- Update
resto6
- Check odd-length palindrome centered at 'a':
-
-
Time Complexity:
$O(n^2)$ , wherenis the length of the string. We expand around each center in the string, and in the worst case, each expansion can take up tonsteps. -
Space Complexity:
$O(1)$ , since we only use a constant amount of additional space for variables.
A string consisting of uppercase english characters can be encoded to a number using the following mapping:
'A' -> "1"
'B' -> "2"
...
'Y' -> "25"
'Z' -> "26"However, while decoding the message, you realize that there are many different ways you can decode the message because some codes are contained in other codes ("2" and "5" vs "25").
For example, "11106" can be decoded into:
"AAJF"with the grouping(1, 1, 10, 6)"KJF"with the grouping(11, 10, 6)- The grouping
(1, 11, 06)is invalid because"06"is not a valid code (only"6"is valid).
Note: there may be strings that are impossible to decode.
Given a string s containing only digits, return the number of ways to decode it. If the entire string cannot be decoded in any valid way, return 0.
The test cases are generated so that the answer fits in a 32-bit integer.
Example 1:
Input: s = "12"
Output: 2
Explanation:
"12" could be decoded as "AB" (1 2) or "L" (12).Example 2:
Input: s = "226"
Output: 3
Explanation:
"226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).Example 3:
Input: s = "06"
Output: 0
Explanation:
"06" cannot be mapped to "F" because of the leading zero ("6" is different from "06"). In this case, the string is not a valid encoding, so return 0.To solve the problem of counting the number of ways to decode the string, I've used a dynamic programming with memoization.
-
Approach:
- We will use a recursive approach with memoization to avoid recalculating results for the same subproblems.
- The recursive function
dfs(i)will compute the number of ways to decode the substring starting from indexi.
-
Base Case:
- If the current index
iis at the end of the string (i == len(s)), we have found a valid decoding, so we return 1.
- If the current index
-
Memoization:
- Use a dictionary
dpto store the results of subproblems. Initializedp[len(s)] = 1because there is one way to decode an empty substring.
- Use a dictionary
-
Recursive Cases:
- If the character at index
iis '0', it cannot be decoded, so we return 0. - Otherwise, compute the result for the single digit decode (
dfs(i + 1)). - If the next two characters form a valid two-digit number (between 10 and 26), add the result of decoding the two digits (
dfs(i + 2)).
- If the character at index
-
Return the Result:
- The result of
dfs(0)will give the number of ways to decode the entire strings.
- The result of
-
Initialization:
- We initialize the memoization dictionary
dpto store results of subproblems. Start withdp = { len(s): 1 }which isdp = { 3: 1 }since the length ofsis 3. - This means that if we are at the end of the string, there is exactly one way to decode an empty substring.
- We initialize the memoization dictionary
-
Recursive Calls:
-
Start at index
i = 0:-
s[0] = '2', which is not '0'. -
Compute
dfs(1)(decoding the substring starting from index 1).-
At index
i = 1:-
s[1] = '2', which is not '0'. -
Compute
dfs(2)(decoding the substring starting from index 2).-
At index
i = 2:-
s[2] = '6', which is not '0'. -
Compute
dfs(3)(decoding the substring starting from index 3).- At index
i = 3:- We have reached the end of the string, so return 1 (base case).
- At index
-
Back to
i = 2:res = 1(number of ways to decode substring from index 2 is 1, i.e., "6").- Store the result in the dictionary:
dp[2] = 1.
-
Check if
s[1:3](i.e., "26") is a valid two-digit decode:- It is valid (between 10 and 26).
- Compute
dfs(3)again:- At index
i = 3:- We have reached the end of the string, so return 1 (base case).
- At index
-
Back to
i = 2:- Add the result:
res += 1(nowres = 2).
- Add the result:
-
-
Store the result in the dictionary:
dp[1] = 2.
-
-
Back to
i = 0:res = 2(number of ways to decode substring from index 1 is 2).
-
Check if
s[0:2](i.e., "22") is a valid two-digit decode:- It is valid (between 10 and 26).
- Compute
dfs(2)again:- At index
i = 2:- Retrieve the result from the dictionary:
dp[2] = 1.
- Retrieve the result from the dictionary:
- At index
-
Back to
i = 0:- Add the result:
res += 1(nowres = 3).
- Add the result:
-
-
Store the result in the dictionary:
dp[0] = 3.
-
-
-
-
Final Result:
dp[0] = 3, so the number of ways to decode the string "226" is 3.
-
Time Complexity:
$O(n)$ , wherenis the length of the string. We process each character at most once due to memoization. -
Space Complexity:
$O(n)$ , due to the recursion stack and the dictionarydpstoring the results of subproblems.
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.
Example 1:
Input: coins = [1,2,5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1Example 2:
Input: coins = [2], amount = 3
Output: -1
Explanation: The target amount is 3, but it is not possible to achieve this amount with the available coin denomination of 2. Using only the coin of 2 would result in a total of 4, which does not match the required amount of 3. Therefore, the function should return -1.Example 3:
Input: coins = [1], amount = 0
Output: 0The idea is to build a solution for the amount from 0 up to the target amount by using previously computed results.
-
Approach:
- We create an array
dpwheredp[i]represents the fewest number of coins needed to make up the amounti. - Initialize
dpwith a value greater than the possible amount (amount + 1), because the maximum number of coins needed to make upamountcannot exceedamount(when using the coin1only). - Set
dp[0]to0because no coins are needed to make the amount0.
- We create an array
-
Dynamic Programming Transition:
- For each amount
afrom1toamount, and for each coincincoins:- If the current amount
ais greater than or equal to the coin valuec, updatedp[a]to the minimum of its current value ordp[a - c] + 1. - This ensures that we are using the fewest number of coins needed to make up the amount
a.
- If the current amount
- For each amount
-
Result:
- If
dp[amount]is still greater thanamount, it means that it is not possible to make up the amount using the given coins, so return-1. - Otherwise, return
dp[amount]as the fewest number of coins needed to make up the amount.
- If
Let's walk through the example coins = [1,2,5], amount = 11 step by step:
-
Initialization:
dp = [0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12](sinceamount + 1 = 12)- Set
dp[0]to0because zero coins are needed to make the amount0.
-
Filling DP Array:
- For
a = 1:- Using coin
1:dp[1] = min(dp[1], 1 + dp[0]) = 1->dp = [0, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12]
- Using coin
- For
a = 2:- Using coin
1:dp[2] = min(dp[2], 1 + dp[1]) = 2 - Using coin
2:dp[2] = min(dp[2], 1 + dp[0]) = 1->dp = [0, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12]
- Using coin
- For
a = 3:- Using coin
1:dp[3] = min(dp[3], 1 + dp[2]) = 2 - Using coin
2:dp[3] = min(dp[3], 1 + dp[1]) = 2->dp = [0, 1, 1, 2, 12, 12, 12, 12, 12, 12, 12, 12]
- Using coin
- Continue filling the array until
a = 11:dp[11] = min(dp[11], 1 + dp[10]) = 3(using coin5twice and coin1once)
- For
-
Result:
- The final
dparray is[0, 1, 1, 2, 2, 1, 2, 2, 3, 3, 2, 3]. - The minimum number of coins to make
11is3(5 + 5 + 1).
- The final
-
Time Complexity:
$O(n \cdot m)$ , wherenis the amount andmis the number of coins. This is because for each amount from1ton, we check allmcoins. -
Space Complexity:
$O(n)$ , wherenis the amount. We use an arraydpof sizen + 1.
Given an integer array nums, find a subarray that has the largest product, and return the product.
A subarray is a contiguous non-empty sequence of elements within an array.
The test cases are generated so that the answer will fit in a 32-bit integer.
Example 1:
Input: nums = [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.Example 2:
Input: nums = [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.The problem is to find the maximum product of a subarray in the given array nums. Due to the possibility of negative numbers and zero, the problem requires careful handling of the product calculations.
-
Initialization:
- We start by initializing the result
resto the maximum value in the array to handle the edge case where the array might have only one negative number or zero. - We also initialize two variables
curMinandcurMaxto1. These will store the minimum and maximum product of the subarray ending at the current position.
- We start by initializing the result
-
Iterate Through the Array:
- For each element
ninnums:- If
nis0, resetcurMinandcurMaxto1because any subarray that includes0will have a product of0. Continue to the next element. - Calculate the temporary maximum product
tmpby multiplyingnwithcurMax. - Update
curMaxto the maximum of:nmultiplied bycurMax(extending the current maximum product subarray),nmultiplied bycurMin(if the current minimum product subarray multiplied by a negative numbernresults in a larger product),nitself (starting a new subarray).
- Update
curMinto the minimum of:tmp(temporary maximum product),nmultiplied bycurMin(extending the current minimum product subarray),nitself (starting a new subarray).
- Update the result
resto the maximum ofresandcurMax.
- If
- For each element
-
Result:
- The maximum product of a subarray is stored in
res.
- The maximum product of a subarray is stored in
Let's walk through the example nums = [2,3,-2,4] step by step:
-
Initialization:
res = max(nums) = 4curMin = 1curMax = 1
-
Iteration:
- For
n = 2:tmp = 2 * 1 = 2curMax = max(2 * 1, 2 * 1, 2) = 2curMin = min(2, 2 * 1, 2) = 2res = max(4, 2) = 4
- For
n = 3:tmp = 3 * 2 = 6curMax = max(3 * 2, 3 * 2, 3) = 6curMin = min(6, 3 * 2, 3) = 3res = max(4, 6) = 6
- For
n = -2:tmp = -2 * 6 = -12curMax = max(-2 * 6, -2 * 3, -2) = -2curMin = min(-12, -2 * 3, -2) = -12res = max(6, -2) = 6
- For
n = 4:tmp = 4 * -2 = -8curMax = max(4 * -2, 4 * -12, 4) = 4curMin = min(-8, 4 * -12, 4) = -48res = max(6, 4) = 6
- For
-
Result:
- The final
resis6, which is the maximum product of a subarray innums.
- The final
-
Time Complexity:
$O(n)$ , wherenis the length of the arraynums. We iterate through the array once. -
Space Complexity:
$O(1)$ , constant space. We use only a few variables (curMin,curMax, andres) regardless of the input size.
Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.
Note that the same word in the dictionary may be reused multiple times in the segmentation.
Example 1:
Input: s = "leetcode", wordDict = ["leet","code"]
Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".Example 2:
Input: s = "applepenapple", wordDict = ["apple","pen"]
Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
Note that you are allowed to reuse a dictionary word.Example 3:
Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
Output: falseThe problem is to determine if the string s can be segmented into a space-separated sequence of one or more dictionary words.
-
Dynamic Programming Array:
- I've used a boolean array
dpwheredp[i]isTrueif the substrings[i:]can be segmented into dictionary words, otherwiseFalse. - Initialize
dp[len(s)]toTruebecause an empty substring can always be segmented.
- I've used a boolean array
-
Iterate Through the String:
- Iterate through the string
sfrom the end to the beginning. - For each position
i, check each word inwordDictto see if the substrings[i:i+len(w)]matches the wordw. - If it matches and the substring
s[i+len(w):]can be segmented (dp[i + len(w)]isTrue), setdp[i]toTrue. - Break the inner loop if
dp[i]becomesTruesince there's no need to check further.
- Iterate through the string
-
Return the Result:
- Finally, return
dp[0]which indicates whether the entire stringscan be segmented into dictionary words.
- Finally, return
Let's walk through the example s = "leetcode", wordDict = ["leet","code"] step by step:
-
Initialization:
dp = [False, False, False, False, False, False, False, False, True]dp[8] = Truebecause the empty string can always be segmented.
-
Iteration:
- For
i = 7to0:- At
i = 7:- No word in
wordDictmatchess[7:], sodp[7]remainsFalse.
- No word in
- At
i = 6:- No word in
wordDictmatchess[6:], sodp[6]remainsFalse.
- No word in
- At
i = 5:- No word in
wordDictmatchess[5:], sodp[5]remainsFalse.
- No word in
- At
i = 4:- The word "code" matches
s[4:8]anddp[8]isTrue, sodp[4]is set toTrue.
- The word "code" matches
- At
i = 3:- No word in
wordDictmatchess[3:], sodp[3]remainsFalse.
- No word in
- At
i = 2:- No word in
wordDictmatchess[2:], sodp[2]remainsFalse.
- No word in
- At
i = 1:- No word in
wordDictmatchess[1:], sodp[1]remainsFalse.
- No word in
- At
i = 0:- The word "leet" matches
s[0:4]anddp[4]isTrue, sodp[0]is set toTrue.
- The word "leet" matches
- At
- For
-
Result:
- The final
dparray is[True, False, False, False, True, False, False, False, True]. dp[0]isTrue, so the string "leetcode" can be segmented as "leet code".
- The final
-
Time Complexity:
$O(n \cdot m)$ , wherenis the length of the stringsandmis the number of words inwordDict. We iterate through the string and for each position, we check each word in the dictionary. -
Space Complexity:
$O(n)$ , wherenis the length of the strings. We use a DP array of sizen + 1.
Given an integer array nums, return the length of the longest strictly increasing
subsequence.
A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.
Example 1:
Input: nums = [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.Example 2:
Input: nums = [0,1,0,3,2,3]
Output: 4Example 3:
Input: nums = [7,7,7,7,7,7,7]
Output: 1I've solved this problem using Dynamic Programming (DP) to find the length of the longest increasing subsequence. The idea is to build a table (array) that stores the length of the longest increasing subsequence ending at each index. This allows us to find the solution by examining all the subsequences that can be formed up to that index.
- Efficient for Subproblems: The problem of finding the longest increasing subsequence is naturally recursive, where you need to check if each element can extend the subsequence formed by earlier elements.
- Optimal Over Brute Force: Instead of recalculating results for every subsequence, DP stores results, allowing us to avoid redundant calculations and improve efficiency.
-
Initialization:
- We create a list
LISwhereLIS[i]represents the length of the longest increasing subsequence ending at indexi. - Initially, each element of
LISis set to1since the minimum subsequence that ends at each index is just the element itself.
- We create a list
-
Iterate from End to Start:
- We loop over each element from right to left (
igoes fromlen(nums) - 1to0). - For each
i, we check the elements that come after it (jfromi + 1tolen(nums)).
- We loop over each element from right to left (
-
Check for Increasing Subsequence:
- If
nums[i] < nums[j], it meansnums[i]can extend the subsequence formed bynums[j]. - We update
LIS[i] = max(LIS[i], 1 + LIS[j])to account for the longer subsequence ending ati.
- If
-
Return the Result:
- Once we finish filling the
LISarray, the length of the longest increasing subsequence will be the maximum value in theLISarray.
- Once we finish filling the
Let’s walk through an example nums = [10,9,2,5,3,7,101,18]:
-
Initialization:
LIS = [1,1,1,1,1,1,1,1](each element represents the longest subsequence ending at that index, starting with 1).
-
Iteration:
-
Starting from the last index (
i = 7), comparenums[i]withnums[j]for allj > i. -
i = 7:nums[7] = 18- No element after index 7, so no update,
LIS = [1,1,1,1,1,1,1,1].
- No element after index 7, so no update,
-
i = 6:nums[6] = 101- Compare
nums[6] < nums[7] (101 < 18)→ False, no update. LIS = [1,1,1,1,1,1,1,1].
- Compare
-
i = 5:nums[5] = 7- Compare
nums[5] < nums[6] (7 < 101)→ True, updateLIS[5] = max(LIS[5], 1 + LIS[6]) = 2. - Compare
nums[5] < nums[7] (7 < 18)→ True, updateLIS[5] = max(LIS[5], 1 + LIS[7]) = 2. LIS = [1,1,1,1,1,3,2,1].
- Compare
-
i = 4:nums[4] = 3- Compare
nums[4] < nums[5] (3 < 7)→ True, updateLIS[4] = max(LIS[4], 1 + LIS[5]) = 4. - Compare
nums[4] < nums[6] (3 < 101)→ True, no change as the update already gave the best result. - Compare
nums[4] < nums[7] (3 < 18)→ True, no change. LIS = [1,1,1,1,4,3,2,1].
- Compare
-
i = 3:nums[3] = 5- Compare
nums[3] < nums[4] (5 < 3)→ False, no update. - Compare
nums[3] < nums[5] (5 < 7)→ True, updateLIS[3] = max(LIS[3], 1 + LIS[5]) = 3. - Compare
nums[3] < nums[6] (5 < 101)→ True, no change. - Compare
nums[3] < nums[7] (5 < 18)→ True, no change. LIS = [1,1,1,3,4,3,2,1].
- Compare
-
i = 2:nums[2] = 2- Compare
nums[2] < nums[3] (2 < 5)→ True, updateLIS[2] = max(LIS[2], 1 + LIS[3]) = 4. - Compare
nums[2] < nums[4] (2 < 3)→ True, no change. - Compare
nums[2] < nums[5] (2 < 7)→ True, no change. - Compare
nums[2] < nums[6] (2 < 101)→ True, no change. - Compare
nums[2] < nums[7] (2 < 18)→ True, no change. LIS = [1,1,4,3,4,3,2,1].
- Compare
-
i = 1:nums[1] = 9- Compare
nums[1] < nums[2] (9 < 2)→ False, no update. - Compare
nums[1] < nums[3] (9 < 5)→ False, no update. - Compare
nums[1] < nums[4] (9 < 3)→ False, no update. - Compare
nums[1] < nums[5] (9 < 7)→ False, no update. - Compare
nums[1] < nums[6] (9 < 101)→ True, updateLIS[1] = max(LIS[1], 1 + LIS[6]) = 2. - Compare
nums[1] < nums[7] (9 < 18)→ True, no change. LIS = [1,2,4,3,4,3,2,1].
- Compare
-
i = 0:nums[0] = 10- Compare
nums[0] < nums[1] (10 < 9)→ False, no update. - Compare
nums[0] < nums[2] (10 < 2)→ False, no update. - Compare
nums[0] < nums[3] (10 < 5)→ False, no update. - Compare
nums[0] < nums[4] (10 < 3)→ False, no update. - Compare
nums[0] < nums[5] (10 < 7)→ False, no update. - Compare
nums[0] < nums[6] (10 < 101)→ True, updateLIS[0] = max(LIS[0], 1 + LIS[6]) = 3. - Compare
nums[0] < nums[7] (10 < 18)→ True, no change. LIS = [3,2,4,3,4,3,2,1].
- Compare
-
-
Final Result:
- The longest increasing subsequence is of length
4([2,3,7,101]).
- The longest increasing subsequence is of length
-
$O(n^2)$ : The solution requires two nested loops. The outer loop iterates over each element, and the inner loop compares the current element with every subsequent element. Thus, the total number of comparisons is proportional ton^2, wherenis the number of elements in the array.
- O(n): We use an additional array
LISof sizento store the length of the longest increasing subsequence at each index. Therefore, the space complexity is linear.