This series is nothing fancy, just pure Leetcode problem breakdown analysis, not to use a sexy line or a niche solution, but with clear code and simple enough thinking to help you clarify the problem. Let you in the interview no longer afraid of algorithm written test.
89. Binary tree expansion to flatten-binary-tree-to-linked-list
The label
- The list
- Binary tree
- medium
The title
Leetcode portal
Let’s just open leetCode.
The root of the binary tree is root. Expand it into a single linked list:
The expanded list should also use TreeNode, with the right child pointing to the next node in the list and the left child always null.
The expanded list should be traversed in the same order as the binary tree.
Example:
Input: root = [6],2,5,3,4 1, null, output: [1, null, 2, null, 3, null, 4, null, 5, null, 6] input: root = [] output: [] input: root = [0] output: [0]Copy the code
The basic idea
And the way we’re going to do this is actually a type of traversal of a binary tree.
See traversal of binary trees
Think about the smallest operation of the problem and break it down! For the first time focus
1 1 1 1 / \ / \ 2! 5 - > 2! 5 -> 2 / \ \ \ \ \ 3! 4! June 3! 6 3\4! 4\5\6Copy the code
This rule is very easy to find, so how to write the program?
We see that the smallest operation on a node is actually flattening a binary tree
- Left subtree becomes right subtree
- The original right subtree hangs at the end of the current right subtree
So how do you flatten a tree into a linked list
-
We first need to level the left subtree and the right subtree to continue to level this node, so the first step is to level the left subtree and the right subtree of root. In other words, the wave recursive operation is in front. (Think of it as a post-order traversal frame)
-
The current node performs the minimum operation:
- Left subtree becomes right subtree
- The original right subtree hangs at the end of the current right subtree
Writing implement
var flatten = function(root) {
if (root === null) {
return null
}
// Perform recursion to level all subtrees, and then perform operation on current node (level current node)
flatten(root.left)
flatten(root.right)
// Now the left and right subtrees are flattened (much like the second figure in the legend)
// Perform minimal operations
let origin_left = root.left
let origin_right = root.right
1. The left subtree becomes the right subtree
root.left = null
root.right = origin_left
// 2. The original right subtree hangs at the end of the current right subtree
// Get the last leveled node as the last mount point
let lastRightNode = root
while(lastRightNode.right ! = =null) {
lastRightNode = lastRightNode.right
}
lastRightNode.right = origin_right
};
Copy the code
90. Distinct subsequences (distinct-intermediate)
The label
- recursive
- DP
- difficult
The title
Leetcode portal
Let’s just open leetCode.
Given a string s and a string t, count the number of occurrences of t in a subsequence of S.
A subsequence of strings is a new string formed by deleting some (or none) characters without interfering with the relative positions of the remaining characters. (For example, “ACE” is a subsequence of “ABCDE”, but “AEC” is not)
The question data ensures that the answers fit into the range of 32-bit signed integers.
Example 1:
Input: s = "rabbbit", t = "rabbit" Output: 3 Explanation: As shown below, there are 3 ways to get "rabbit" from S. Arrow symbols on (^) characters that selecting rabbbit ^ ^ ^ ^ ^ ^ rabbbit ^ ^ ^ ^ ^ ^ rabbbit ^ ^ ^ ^ ^ ^Copy the code
It’s just finding the number of solutions.
The basic idea
When you see this kind of problem, you think of dynamic programming, looking for recursive formulas, which is really looking for relationships.
If you are not familiar with the basic concepts of dynamic programming, move to DP Basics
Basic steps
Let’s look at it from these three perspectives
- Search for optimal substructure (state representation)
- Induction of state transition Equation (State calculation)
- Boundary initialization
The problem itself counts the number of occurrences of T in a subsequence of S.
So let’s simplify things, we can actually imagine that these two strings are a little bit shorter, and we create two Pointers I and j
- State said:
dp[i][j]
saids[0~i)
Subsequence of andt[0~j)
The emergence ofThe number ofSubproblems. Let’s cut short s and t, respectively
For example, s = "babgbag", t = "bag" I j note that < I,j closed before open so we cut short s' = S [0~ I) = "babgba" t' = t[0~j) = "ba" which is actually the last digit let's get rid of it, So this simplifies the problem and the solution to the original problem is dp[S.length][T.length]Copy the code
The relationship between the subproblem and the original problem is, in fact, the inference of the state transition equation
-
State transition equation
- Think easy first, if
s[i] ! == t[j]
, indicating that even if s is subtracted by one, it does not affect the original problemdp[i][j] = dp[i - 1][j]
Similar to s = ‘abcxxxx’ t = ‘ABC’, you can cut the x after s without affecting the original result. - And then if
s[i] === t[j]
So there are two cases,- One is the
The last digit is the necessary digit
则dp[i - 1][j - 1]
I don't need the last one, I can just drop it
Because it’s already set updp[i - 1][j]
- One is the
- So the equation is
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
- Think easy first, if
-
The boundary conditions
- We can do it at
dp[i][j]
An empty string is inserted in front of it to indicate that a blank can be selected. Select “” empty, (j = 0) thent = ""
,dp[i][0] = 1
Each substring is a solution, because an empty string is a subsequence of any string - When I = 0, there can be no solution dp[0][j] = 0
- We can do it at
The following code is clear
Writing implement
var numDistinct = function(s, t) {
// index = 0; // index = 0
let [m, n] = [s.length + 1, t.length + 1]
if (m < n) {
return 0
}
let dp = new Array(m).fill(0).map(
item= > new Array(n).fill(0))for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
// Empty string is a subset of empty string
if (j === 0) {
dp[i][j] = 1
} else if (i === 0) {
dp[i][j] = 0
} else {
if (s[i-1] === t[j-1]) {
dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
} else {
dp[i][j] = dp[i-1][j]
}
}
}
}
return dp[m - 1][n - 1]};let s = "babgbag", t = "bag"
console.log(numDistinct(s, t));
Copy the code
In addition, I would like to recommend the article of the eldest brother to you. It is very simple and profound. It is very effective for the students who advance in the front end. Core concepts and algorithm disassembly series
That’s all for today. If you want to work with me, you can add me to my wechat account infinity_9368, and you can chat with me and add my secret code “Tianwang Gedi Hu”. Verify the message please send me presious tower shock the rever monster, I see it through, the code is not on the ha, add after I will do my best to help you, but pay attention to the way of asking questions, suggest reading this article first: the wisdom of asking questions
reference
- Juejin. Cn/post / 690975…