头图

Zero title: Algorithm (leetcode, with mind map + all solutions) of 300 questions (2312) sell wood blocks

a topic description

题目描述
题目描述

Two solutions overview (mind map)

思维导图

All three solutions

Interviewer: Seeing that you are almost ready, let's start the interview.

Madman Zhang San: okk~

Interviewer: If the topic is almost the same, let’s talk about your thoughts and ideas~

Madman Zhang San: Because the title contains the word "most" , I think the use of "dynamic programming" should be given priority.

Interviewer: Then what do you think are the conditions for using dynamic programming?

Madman Zhang San: I personally think that two conditions should be met:

**1) Optimal substructure

2) No aftereffect
**

Interviewer: Very good, then do you know the essence of dynamic programming and the steps to solve the problem?

Madman Zhang San:

**1) Essence: a technology that trades space for time

2) Problem solving steps: There are 3 steps. State definition: the decision of each state, storing the variables of each state; state transition equation: the transition relationship between the current state and the previous state; initial state: the initial state or boundary conditions, etc. **

Interviewer: Boy, yes. I think you are almost done with the heat, so you can use the above knowledge to solve this problem~

Narrator: After 5-10 minutes, Zhang San couldn't write the code for a long time.

Interviewer: (with a dignified and confused look) Have you only memorized the relevant concepts and never coded the relevant topics?

Madman Zhang San: (Zhang San loses his timid expression) Uh. . . .

Interviewer: In this way, you can imagine the wooden block as a big watermelon, and it will be cool and refreshing when you write the code~
Then the problem becomes - you have a large watermelon with a two-dimensional (length w, width h) , you can choose to sell it directly (if someone happens to buy a length w and a width h at this time) ), otherwise the big watermelon at this time can only get 0 yuan

Madman Zhang San: Yes, then we can also choose not to sell the big watermelon at this time, cut the melon horizontally and vertically, cut the big watermelon into different small watermelons continuously, and finally calculate the current The maximum price that a large watermelon can be sold for.

Interviewer: Yes, then according to what you said before, write down the state definition and state transition equation~

Madman Zhang San: Okay.

The definition of state as I understand it - dpi, the maximum amount of money that can be obtained when the length is i and the width is j.

State transition equation - when cutting the melon horizontally: dpi = max(dpi, dpk + dpi - k), and the range of k is [1, i - 1].
When cutting melon vertically: dpi = max(dpi, dpi + dpi), the range of k is [1, j - 1].

Interviewer: What about the initialization of the state?

Madman Zhang San: Initialize according to the array prices - when i and j exist at the subscript positions of 0 and 1 in prices, dpi = the subscript of the element corresponding to prices.

Interviewer: Very good, since the idea has been sorted out, then start your performance, ah no, start your code writing~

Next to: Zhang San was like Ren and Du’s second vein being opened up in an instant, and he typed out the code in less than 10 minutes~

1 Scenario 1

1) Code:

 // 方案1 “动态规划法 - 普通版”。
// “技巧:题干中含有 最 字眼,优先考虑动态规划(本质:以空间换时间的技术)。”
// 参考:
// 1)https://leetcode.cn/problems/selling-pieces-of-wood/solution/mai-mu-tou-kuai-by-leetcode-solution-gflg/
// 2)https://leetcode.cn/problems/selling-pieces-of-wood/solution/by-endlesscheng-mrmd/

// 想法(这里把木块想象成大西瓜,写起代码来也会嘎嘎的清凉和爽快哦~):
// 1)状态定义:dp[i][j],长度为i、宽度为j时,能得到的最多钱数。
// 2)状态转移:
// 2.1)横向切:dp[i][j] = max(dp[i][j], dp[k][j] + dp[i - k][j]),k的范围为 [1, i - 1]。
// 2.2)纵向切:dp[i][j] = max(dp[i][j], dp[i][k] + dp[i][j - k]),k的范围为 [1, j - 1]。

// 思路:
// 1.1)状态初始化:l = prices.length; 
// dp = new Array(m + 1).fill(1).map(v => new Array(n + 1).fill(0));
// 思考:二维的每个元素为啥都先 默认填充0 ?
// 1.2)状态初始化:遍历 数组 prices ,进一步初始化 数组 dp 。

// 2)核心:状态转移。
// 2.1)横向切:dp[i][j] = max(dp[i][j], dp[k][j] + dp[i - k][j]),k的范围为 [1, i - 1]。
// 2.2)纵向切:dp[i][j] = max(dp[i][j], dp[i][k] + dp[i][j - k]),k的范围为 [1, j - 1]。

// 3)返回结果 dp[m][n] 。
var sellingWood = function(m, n, prices) {
    // 1.1)状态初始化:l = prices.length; 
    // dp = new Array(m + 1).fill(1).map(v => new Array(n + 1).fill(0));
    // 思考:二维的每个元素为啥都先 默认填充0 ?
    const l = prices.length;
    let dp = new Array(m + 1).fill(1).map(v => new Array(n + 1).fill(0));

    // 1.2)状态初始化:遍历 数组 prices ,进一步初始化 数组 dp 。
    for (let i = 0; i < l; i++) {
        const [width, height, price] = prices[i];
        dp[width][height] = price;
    }
    
    // 2)核心:状态转移。
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            // 2.1)横向切:dp[i][j] = max(dp[i][j], dp[k][j] + dp[i - k][j]),k的范围为 [1, i - 1]。
            for (let k = 1; k < i; k++) {
                dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]);
            }
            // 2.2)纵向切:dp[i][j] = max(dp[i][j], dp[i][k] + dp[i][j - k]),k的范围为 [1, j - 1]。
            for (let k = 1; k < j; k++) {
                dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]);
            }
        }
    }

    // 3)返回结果 dp[m][n] 。
    return dp[m][n];
};

2 Option 2

Interviewer: Good. The code structure is very hierarchical, and the comments are also placed in a very suitable position~

Madman Zhang San: After all, this "two-dimensional big watermelon" is guaranteed to be ripe. I can guarantee that the algorithm here must be optimal and can guarantee the highest price for our big watermelon.

Interviewer: Are you sure that your "big watermelon cutting algorithm" is ripe? I don't think so?

Madman Zhang San: I am a serious algorithm person, can I still write you the "raw melon algorithm"?


Interviewer: I ask you, is this "big watermelon cutting algorithm" guaranteed to be ripe?

Madman Zhang San: Just tell me if I can pass this interview~


Interviewer:


Madman Zhang San: Then I'll take a look and think about optimization.

Narrator: I saw Zhang San wrote the code running process on the paper.
...
dp5 = max(dp5, dp1 + dp4, dp2 + dp3, dp3 + dp2, dp2 + dp1)
...

Madman Zhang San: It seems that there is indeed an optimization point - there are a lot of redundant calculations, we only need to enumerate the subscript k to half the position - that is, the range of k is [1, i / 2 (downwards) Rounding)] .

1) Code:

 // 方案2 “动态规划法 - 优化版”。
// “技巧:题干中含有 最 字眼,优先考虑动态规划(本质:以空间换时间的技术)。”
// 参考:
// 1)https://leetcode.cn/problems/selling-pieces-of-wood/solution/mai-mu-tou-kuai-by-leetcode-solution-gflg/
// 2)https://leetcode.cn/problems/selling-pieces-of-wood/solution/by-endlesscheng-mrmd/

// 想法(这里把木块想象成大西瓜,写起代码来也会嘎嘎的清凉和爽快哦~):
// 1)状态定义:dp[i][j],长度为i、宽度为j时,能得到的最多钱数。
// 2)状态转移:
// 2.1)横向切:dp[i][j] = max(dp[i][j], dp[k][j] + dp[i - k][j]),k的范围为 [1, i - 1]。
// 2.2)纵向切:dp[i][j] = max(dp[i][j], dp[i][k] + dp[i][j - k]),k的范围为 [1, j - 1]。

// 思路:
// 1.1)状态初始化:l = prices.length; 
// dp = new Array(m + 1).fill(1).map(v => new Array(n + 1).fill(0));
// 思考:二维的每个元素为啥都先 默认填充0 ?
// 1.2)状态初始化:遍历 数组 prices ,进一步初始化 数组 dp 。

// 2)核心:状态转移(有优化,存在对称性,k枚举到i、j的1半的位置即可)。
// 2.1)横向切:dp[i][j] = max(dp[i][j], dp[k][j] + dp[i - k][j]),k的范围为 [1, i / 2(向下取整)]。
// 2.2)纵向切:dp[i][j] = max(dp[i][j], dp[i][k] + dp[i][j - k]),k的范围为 [1, j / 2(向下取整)]。

// 3)返回结果 dp[m][n] 。
var sellingWood = function(m, n, prices) {
    // 1.1)状态初始化:l = prices.length; 
    // dp = new Array(m + 1).fill(1).map(v => new Array(n + 1).fill(0));
    // 思考:二维的每个元素为啥都先 默认填充0 ?
    const l = prices.length;
    let dp = new Array(m + 1).fill(1).map(v => new Array(n + 1).fill(0));

    // 1.2)状态初始化:遍历 数组 prices ,进一步初始化 数组 dp 。
    for (let i = 0; i < l; i++) {
        const [width, height, price] = prices[i];
        dp[width][height] = price;
    }
    
    // 2)核心:状态转移。
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            // 2.1)横向切:dp[i][j] = max(dp[i][j], dp[k][j] + dp[i - k][j]),k的范围为 [1, i / 2(向下取整)]。
            for (let k = 1; k <= Math.floor(i / 2); k++) {
                dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]);
            }
            // 2.2)纵向切:dp[i][j] = max(dp[i][j], dp[i][k] + dp[i][j - k]),k的范围为 [1, j / 2(向下取整)]。
            for (let k = 1; k <= Math.floor(j / 2); k++) {
                dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]);
            }
        }
    }

    // 3)返回结果 dp[m][n] 。
    return dp[m][n];
};

Narrator: After Zhang San wrote the above code, he hurriedly asked the interviewer.

Madman Zhang San: Did you pass the interview?

Interviewer:


Madman Zhang San:

Another offer, and I'm going to be the CEO soon. Should I go to eat Shaxian snacks in the evening? Or Lanzhou Ramen ? Alas, having too many choices is also an annoyance!

Four resource sharing & more

1 Historical Articles - Overview

Article name solution reading volume
1. Two Sum 3 types in total 2.7k+
2. Add Two Numbers 4 types in total 2.7k+
3. Longest Substring Without Repeating Characters 3 types in total 2.6k+
4. Find the Median of Two Sorted Arrays 3 types in total 2.8k+
5. Longest Palindromic Substring 4 types in total 2.8k+
6. ZigZag Conversion 2 types in total 1.9k+
7. Reverse Integer 2 types in total 2.4k+
8. String to Integer (atoi) 3 types in total 4.2k+
9. Palindrome Number 3 types in total 4.3k+
11. Container With Most Water 5 in total 4.0k+
12. Integer to Roman 3 types in total 3.2k+
13. Roman to Integer 3 types in total 3.8k+
14. Longest Common Prefix 4 types in total 3.0k+
15. The Sum of Three Numbers (3Sum) 3 types in total 60.7k+
16. 3Sum Closest 3 types in total 4.7k+
17. Letter Combinations of a Phone Number 3 types in total 3.1k+
18. The sum of four numbers (4Sum) 4 types in total 11.5k+
19. Remove Nth Node From End of List 4 types in total 1.2k+
20. Valid Parentheses 2 types in total 1.8k+
21. Merge Two Sorted Lists 3 types in total 1.2k+
22. Generate Parentheses 4 types in total 1.1k+
23. Merge k Sorted Lists 4 types in total 0.9k+
24. Swap Nodes in Pairs 3 types in total 0.5k+
25. Reverse Nodes in k-Group 5 in total 1.3k+
26. Remove Duplicates from Sorted Array 4 types in total 1.3k+
27. Remove Element 4 types in total 0.4k+
28. Implement strStr() (Implement strStr()) 5 in total 0.8k+
29. Divide Two Integers 4 types in total 0.6k+
30. Substring with Concatenation of All Words 3 types in total 0.6k+
31. Next Permutation 2 types in total 0.8k+
32. Longest Valid Parentheses 2 types in total 1.4k+
33. Search in Rotated Sorted Array 3 types in total 1.0k+
34. Find First and Last Position of Element in Sorted Array 3 types in total 0.5k+
35. Search Insert Position 3 types in total 0.3k+
36. Valid Sudoku 1 in total 0.6k+
38. Count and Say 5 in total 1.1k+
39. Combination Sum 3 types in total 1.4k+
40. Combination Sum II 2 types in total 1.6k+
41. First Missing Positive 3 types in total 1.2k+
53. Maximum Subarray Sum (Maximum Subarray) 3 types in total 0.3k+
88. Merge Sorted Array 3 types in total 0.4k+
102. Binary Tree Level Order Traversal 3 types in total 0.4k+
146. LRU Cache (LRU Cache) 2 types in total 0.5k+
160. Intersection of Two Linked Lists 2 types in total 0.1k+
200. Number of Islands 4 types in total 0.1k+
206. Reverse Linked List 3 types in total 1.0k+
215. Kth Largest Element in an Array 3 types in total 0.5k+
236. Lowest Common Ancestor of a Binary Tree 3 types in total 0.1k+
2119. A Number After a Double Reversal 2 types in total 0.3k+
2120. Execution of All Suffix Instructions Staying in a Grid 1 in total 0.4k+
2124. Check if All A's Appears Before All B's 4 types in total 0.4k+
2125. Number of Laser Beams in a Bank 3 types in total 0.3k+
2126. Destroying Asteroids 2 types in total 1.6k+
2129. Capitalize the Title 2 types in total 0.6k+
2130. Maximum Twin Sum of a Linked List 2 types in total 0.6k+
2133. Check if Every Row and Column Contains All Numbers 1 in total 0.6k+

刷题进度 - LeetCode:557 / 2689 、《剑指offer》:66 / 66

2 Introduction to bloggers

Code Farmer Sanshao, a blogger dedicated to writing minimalist but complete problem solutions (algorithms ).
Focus on one question, multiple solutions, structured thinking , welcome to brush through LeetCode ~


码农三少
54 声望8 粉丝