Use three interview questions to understand the basic logic of dynamic programming (strike while the iron is hot, the second one)

Link to the original title: 300. Longest Ascending Subsequence (LIS)

Click here to conquer the first one! ! !
Title description:

Give you an integer array nums and find the length of the longest strictly increasing subsequence.

A subsequence is a sequence derived from an array, deleting (or not deleting) elements in the array without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].
 

Example 1:

Input: nums = [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], so the length is 4.

Example 2:

Input: nums = [0,1,0,3,2,3]
Output: 4

Example 3:

Input: nums = [7,7,7,7,7,7,7]
Output: 1

 

prompt:

    1 <= nums.length <= 2500
    -104 <= nums[i] <= 104

Source: LeetCode (LeetCode)
Link: https://leetcode-cn.com/problems/longest-increasing-subsequence
Copyright is owned by LeetCode . For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Question ideas:

1. A brief introduction to dynamic programming

Dynamic Programming (Dynamic Programming), referred to as dp, is a common strategy for solving optimization problems. Generally speaking, using dynamic programming to solve problems is nothing more than three steps.

1.1 Define the state (the state is the original problem, the solution of the sub-problem), such as defining the meaning of dp(i)

1.2 Set the initial state (boundary), such as setting the value of dp(0)

1.3 Determine the state transition equation, such as determining the relationship between dp(i) and dp(i-1)

2. So using these three steps, let us see how to solve the above problem.

2.1 Assuming the value of nums is {10,2,2,5,1,7,101,18}, it is obvious that the maximum increasing subsequence is {2,5,7,101} and {2,5,7,18} . Length 4

2.2 Define status

Assuming dp(i) is the length of the longest increasing subsequence ending in nums[i], what does it mean? E.g

nums[0], the longest ascending subsequence ending in 10 is 10, so dp(0) = 1

nums[1], the longest ascending subsequence at the end of 2 is 2, so dp(1) = 1

nums[2], the longest ascending subsequence at the end of 2 is 2, so dp(2) = 1

nums[3], the longest ascending subsequence at the end of 5 is 2, 5, so dp(3) = dp(1) + 1 = dp(2) + 1 = 2, where dp(1) and dp(2 ) It means that the first 2 and the second 2 can be combined with 5 to form the top ascending subsequence

nums[4], the longest ascending subsequence at the end of 1 is 1, so dp(4) = 1

The longest ascending subsequence at the end of nums[5], 7 is 2, 5, 7, so dp(5) = dp(3) + 1 = 3

The longest ascending subsequence at the end of nums[6], 101 is 2, 5, 7, 101, so dp(6) = dp(5) + 1 = 4

nums[7], the longest ascending subsequence ending in 18 is 2, 5, 7, 18, so dp(7) = dp(5) + 1 = 4

So we can find that the element that can be the longest ascending subsequence of splicing must meet two conditions. First, the current element must be greater than the end value of the longest ascending subsequence before. Because it is rising, it must be larger. , Otherwise it cannot be spliced. Secondly, the length after splicing is the longest

2.3 State transition equation

Traverse j∈[0, i)

If nums[i]> nums[j], nums[i] can be spliced ​​after nums[j] to form an ascending subsequence longer than dp(j), the length is dp(j) + 1, so dp( j) = max{dp(i), dp(j) + 1}

If nums[i] <= nums[j], nums[i] cannot be spliced ​​after nums[j], skip this traversal

2.4 Initial state

dp(0) = 1, because there is only one element, the length must be only 1. All dp(i) are initialized to 1 by default, because we want to prevent {3,5,1,10} from appearing when i is equal to 2. , Is element 1, then if dp(i) is not initialized to 1, then in the code, element 1 will definitely skip 3 and 5, dp(2) = 0, obviously does not meet the meaning of the question, because there is only one element When, its length is 1, so it needs to be initialized to 1.

3. If it is too obscure, then I will explain it in plain English

For example, you are now playing King of Glory. The elements in the nums[] array are the combat power of each player. In dp(i) is the number of people forming a team that ends with i. Because King of Glory is a team battle, each team must take turns to choose The captain, in other words, every player who can join the team is the captain’s strength and is selected based on the best. Just like the team has two people {village player, provincial player}, then when this team is selecting people, it must be It is hoped that players from the national service will join and take up the position of captain. For example, if there is a team with a strength of {2, 4, 5, 10}, then when the team chooses the next captain, only those with a strength greater than 10 will have Qualified to join the team, players with a combat power of less than 10 will be eliminated, and so on, eventually the team with the largest number of people will appear. That kind of team is the answer we need.

Don’t talk nonsense, just go to the code, in order to let the judges understand more clearly, my code is not written concisely, I add a lot of comments to the code, I believe that the judges can understand, if I did not write clearly or If you make a mistake, you can comment in the area or send a private message to me

class Solution {
    public int lengthOfLIS(int[] nums) {
        if(nums == null || nums.length == 0) return 0;
        int[] dp = new int[nums.length];    //由于我是从0下标开始,所以不用nums.length+1
        int max = dp[0] = 1;    //假设只有一个元素,那么最长度就是1
        for(int i = 1; i < nums.length; i++){
            dp[i] = 1;      //如果出现当前的元素是比之前的每条子序列最末位的数小,说明不能加进去,所以当前的元素的拼成的子序列,只有它本身,也就是长度是1
            for(int j = 0; j < i; j++){     
            //如果出现当前的元素是没有比之前的每条子序列最末位的数大,说明不能加进去,就跳过
                if(nums[i] <= nums[j]) continue;
                //代码执行到这里,说明当前元素是比子序列最末位的数大,所以把这个元素加到末尾
                //所以才有dp[j] + 1
                dp[i] = Math.max(dp[i],dp[j] + 1);
                //取出较大值
                max = Math.max(max,dp[i]);
            }
        }
        //返回长度最长的值
        return max;
    }
}

I've seen it all here, don't you think about clicking a like before leaving? If you don’t like it, my heart will be Bingbing.

Guess you like

Origin blog.csdn.net/qq_45798556/article/details/114880742