- Written on May 29, 2019
70. Climb stairs
① Title description
- Suppose you are climbing stairs. It takes n steps to reach the top of the building.
- You can climb 1 or 2 steps each time. How many different ways do you have to climb to the top of a building?
- Note: Given n is a positive integer.
- Example 1:
Input: 2
Output: 2
Explanation: There are two ways to climb to the top of the building.
- 1st order + 1st order
- Level 2
- Example 2:
Input: 3
Output: 3
Explanation: There are three ways to climb to the top of the building.
- 1st order + 1st order + 1st order
- 1st order + 2nd order
- 2nd order + 1st order
② Recursive solution ( Time Limit Exceeded
)
- Want to use recursive thinking about requiring n layer step moves, due to the time to go one or two steps, before it is up to the n-th stage, must remain at the
n - 1
previous level, orn - 2
on a stage. So if f (n) is used to represent the movement of n steps. Then,
f ( n ) = f ( n - 1) + f ( n - 2 )
f ( 1 ) = 1,f ( 2 ) = 2
- Found a magical thing, this is the Fibonacci sequence (Fibonacci sequence).
- Just be violent and write it out using recursion. However, it turned out to be 37 o'clock
Time Limit Exceeded
! - Time complexity: is a tree diagram, O (2 n) O(2^n)O ( 2n)。
- code show as below:
public int climbStairs(int n) {
if (n == 1) {
return 1;
}
if (n == 2) {
return 2;
}
return climbStairs(n - 2) + climbStairs(n - 1);
}
③ Recursive optimization
- With
f(4)
, for example, we need to solve, respectively,f(3)
andf(2)
; solvingf(3)
, Xie points need to solvef(2)
andf(1)
, in fact,f(2)
already been solved before.
- Optimization is to find solutions have kept up demand behind when used directly, without re-entering the recursion, called the
memoization
technology. - This technique is also used in the optimization of the previous recursive method!
- code show as below:
public int climbStairs(int n) {
HashMap<Integer, Integer> map = new HashMap<>();
return climbStairsN(n, map);
}
public int climbStairsN(int n, HashMap<Integer, Integer> map) {
if (n == 1) {
return 1;
}
if (n == 2) {
return 2;
}
int f1 = 0;
if (map.containsKey(n - 1)) {
f1 = map.get(n - 1);
} else {
f1 = climbStairsN(n - 1, map);
map.put(n - 1, f1);
}
int f2 = 0;
if (map.containsKey(n - 2)) {
f2 = map.get(n - 2);
} else {
f2 = climbStairsN(n - 2, map);
map.put(n - 2, f2);
}
map.put(n, f1 + f2);
return f1 + f2;
}
④ Use array
- Create a new array
f[]
to store the Fibonacci sequence, initialize itf[1] = 1, f[2] = 2;
, thenf[i] = f[i - 1] + f[i - 2]
. - Although the space complexity is O (n) O(n)O ( n ) , but the time complexity becomesO (n) O(n)O ( n ) , so the running time is
0ms
. - code show as below:
public int climbStairs(int n) {
if (n == 1) {
return 1;
}
if (n == 2) {
return 2;
}
int[] f = new int[n + 1];
f[1] = 1;
f[2] = 2;
for (int i = 3; i <= n; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f[n];
}
72. Edit distance
② Title description
- Given two words
word1
andword2
to calculate theword1
convertedword2
minimum number of operations used. - You can perform the following three operations on a word:
insert a character,
delete a character,
replace a character - Example 1:
Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation:
horse -> rorse (replace'h'
with'r ') rorse -> rose (delete'r')
rose -> ros (delete' e')
- Example 2:
Input: word1 = “intention”, word2 = “execution”
Output: 5
Explanation: intention -> inention (delete't')
inention -> enention (
replace'i ' with'e ') enention -> exention (change' replace
n'with'x ') exention -> exection (replace'n ' with'c')
exection -> execution ( insert'u ')
② Dynamic programming
dp[i][j]
For stringsword1[ 0, i )
(word1 the 0th to i - 1 character) and aword2[ 0, j - 1)
minimum edit distance.- State transition equation:
① Ifword1[i -1] = word2[j - 1]
,dp[i][j] = dp[i - 1][j - 1]
because the character has not changed.
② Ifword1[i -1] != word2[j - 1]
, ,dp[i][j] = Math.min(dp[i][j - 1], Math.min(dp[i - 1][j], dp[i - 1][j - 1])) + 1
respectively word1 add, delete, replace a character becomes word2. - Initialization:
①dp[0][0]=0
, means that the length of both are 0, and the minimum edit distance is 0;
② From thei = 1
beginningdp[i][0] = i
,, means the steps needed to delete characters from word1 to empty word2;
③ From thej = 1
beginningdp[0][j] = j
,, means that word1 changes from empty characters to characters The steps required for word2.
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m + 1][n + 1];
// word1有非空变为空所需要的删除步骤
for (int i = 1; i <= m; i++) {
dp[i][0] = i;
}
// word1由空变成 word2所需要的添加的步骤
for (int j = 1; j <= n; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
// word1的下标i-1.其实表示第i个字符,也就是我们当前要求解的字符
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
// min( add, delete, change)+1
dp[i][j] = Math.min(dp[i][j - 1], Math.min(dp[i - 1][j], dp[i - 1][j - 1])) + 1;
}
}
}
return dp[m][n];
}
75. Color Classification
① Title description
- Given an array of n elements containing red, white and blue, sort them in place so that the elements of the same color are adjacent and arranged in the order of red, white, and blue.
- In this question, we use integers 0, 1, and 2 to represent red, white, and blue, respectively.
- Note: You cannot use the sorting function in the code base to solve this problem.
- Example:
Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
- Advanced:
An intuitive solution is to use a two-pass scanning algorithm for counting sorting.
First, iteratively calculate the number of elements 0, 1, and 2, and then rewrite the current array in the order of 0, 1, and 2.
Can you think of a one-pass scanning algorithm that uses only constant space?
② Double pointer (own idea)
- It must be
0,...,0 1,...,1 2,...,2
the case after the array is sorted . We can think of it as three parts, each of which is the number 0, 1, and 2, respectively. - Therefore, the outer loop has a total of 3 times. In each pass, do not put all 0s in the first segment, all 1s in the second segment, and all in the third segment.
- The inner loop uses double pointers
start指针
to indicate the position of the number to be inserted, andcur指针
constantly moves backward to find the number that can be inserted. - In each memory loop, if it
nums[start]
happens to be i, the point of start needs to be updated, and start cannot cross the boundary; after determining the position of the number to be inserted, curstart+1
traverses the array from the beginning to the back to find the number that can be inserted. - No number can be inserted, cur points to the next number; otherwise start and cur point to the next number at the same time.
- code show as below:
public void sortColors(int[] nums) {
if (nums.length == 0 || nums.length == 1) {
return;
}
int start = 0;
for (int i = 0; i < 3; i++) {
while (start < nums.length && nums[start] == i) {
start++;
}
int cur = start + 1;
while (cur < nums.length) {
// cur向后遍历,直到遍历完数组
if (nums[cur] == i) {
// 找到了待插入的数字,交换cur和start指向数字
int temp = nums[start];
nums[start] = nums[cur];
nums[cur] = temp;
start++; // start+1指向下一个待插入数字的位置
}
cur++;
}
}
}
③ Count the number of 0 and 1, add the corresponding number of 0,1,2 to the array
- code show as below:
public void sortColors(int[] nums) {
if (nums.length == 0 || nums.length == 1) {
return;
}
int zero_count = 0;
int one_count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) {
zero_count++;
}
if (nums[i] == 1) {
one_count++;
}
}
// 将对应位置的数字改为对应数目的0,1,2
for (int i = 0; i < nums.length; i++) {
if (zero_count > 0) {
nums[i] = 0;
zero_count--;
} else if (one_count > 0) {
// 只有当0的个数加满后,才能添加1
nums[i] = 1;
one_count--;
} else {
nums[i] = 2;
}
}
}