In mathematical terms, incursion is more commonly related to simple induction. Likewise, dynamic programming is related to strong induction. The strong induction approach also naturally ties in with recursion. However, a naive recursive approach often results in exponential time complexity due to redundant calculations. To optimize, dynamic programming or other algorithms are usually applied.
For a rigorous mathematical example of strong induction, one can refer to the NYU 6003 Foundation of Computer Science Homework. In this article, however, the focus will be on its applications in solving LeetCode questions.
After Learning the strong induction part, you should easily solving the following leetcode questions.
Beginning Questions:
Questions Easy Level Leetcodes
1-D Dynamic
70. Climbing Stairs
The recursive approach:
class Solution {
public:
int climbStairs(int n) {
if(n == 0 || n == 1 || n == 2) return n;
return climbStairs(n-1) + climbStairs(n-2);
}
};
This solution has exponential time complexity (O(2^n)) due to redundant calculations. To optimize:
The dynamic programming approach:
//use vector to remember
if(n == 0 || n == 1) return 1; //edge cases
vector<int> dp(n+1); //!very important because we going to access dp[n], so we need n+1 elememts
dp[0] = dp[1] = 1;
for(int i = 2; i <= n; i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
这里只用0,1 因为只踩踏俩个,所以只需n-1,n-2. 预备俩位即可
For a detailed explanation and another space optimization method, click here.
746. Min Cost Climbing Stairs
Solution by author:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int> curr(cost.size()+1);
curr[0] = 0, curr[1] = 0;
for(int i = 2; i < curr.size(); i++){
curr[i] = min(curr[i-2]+cost[i-2], curr[i-1]+cost[i-1]);
}
return curr[cost.size()];
}
};
Time complexity: O(n), Space Complexity: O(n)
Optimized solution:
Minimize the space complexity from O(n) to O(1) by only record the curr[n-1] and curr[n-2].
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n = cost.size();
int prev = 0, curr = 0;
for (int i = 2; i <= n; i++) {
int next = min(curr + cost[i - 1], prev + cost[i - 2]);
prev = curr;
curr = next;
}
return curr;
}
};
Time complexity: O(n), Space Complexity: O(1)
Medium Leetcode Questions
Both problems utilize a similar logic as discussed above.
这是第一道不是所有存在值都有对应值的题,并且每个i的对应值都不止一个,所以思考起来有些复杂。值得多次做题。
279. Perfect Squares 这道题和coin change很像。在做题的时候记住一个10000长度的array不是长 array。是刚刚好的array.
2-D Dynamic Programming
Many dynamic programming problems revolve around 2-D arrays. Here are some exemplar problems:
62. Unique Paths
int path[m][n];
//最上行和最左列都是0
for(int i = 0; i < m; i++){
path[i][0] = 1;
}
for(int i = 0; i < n; i++){
path[0][i] = 1;
}
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
path[i][j] = path[i][j-1] + path[i-1][j];
}
}
return path[m-1][n-1];
same logic Pay attention to the difference between vector<vector>grid[m][n] and int dp[n][m]
5. Longest Palindromic Substring 647. Palindromic Substrings same logic
53. Maximum Subarray 152. Maximum Product Subarray
Challenging Dynamic Programming Questions
Below is a list of dynamic programming questions that are trickier and might require more thought upon first encounter: