Use three interview questions to understand the basic logic of dynamic programming (finally evolve to the third one)

Click here to conquer the first one! ! !

Click here to conquer the second way! ! !
Title description:

Find the length of the longest common subsequence of two int arrays nums1 and nums2. What is a subsequence? The subsequence starts from the right to the left, and can be a non-contiguous sequence. For example, the longest common subsequence of [1,3,5,9,10] and [1,4,9,10] is [1,9] ,10], so the length is 3; for example, the longest common subsequence of [1,5,11,22,88] and [5,4,2,11,8] is [5,11] with length 2, remember The subsequence is not a substring, the substring is continuous, and the subsequence may not be continuous.

Question ideas:

1. In fact, dynamic programming is a process of continuous optimization. Next, I will solve this problem in four ways, and the efficiency is continuously improved, the code is continuously optimized, but the overall idea has not changed much, just Partially optimized.

2. Assuming that dp(i,j) is the longest common subsequence length of [nums1 first i elements] and [nums2 first j elements]

The initial values ​​of dp(0,j) and dp(i,0) are both 0, because dp(0,j) represents the length of the longest common subsequence of [nums1 first 0 elements] and [nums2 first j elements], That must be 0, there is no public part at this time.

2.1 If nums1 [i-1] == nums2 [j-1], then dp (i, j) = dp (i-1, j-1) + 1, because for example [1, 3, 5, 9, 10 ] And [1, 4, 9, 10], when traversing to nums1 [3] and nums2 [2], element 9 and element 9 are equal, so no matter how you calculate, the longest common sub of the two arrays The sequence length must be at least 1, so we have to add the longest common subsequence before, which is dp(i-1, j-1), which is the longest common subsequence at this time.

2.2 If nums1 [i-1] != nums2 [j-1], then dp (i, j) = max {dp (i-1, j), dp (i, j-1)}, max represents this The larger value of the set, such as [1, 3, 5, 9, 10] and [1, 4, 9, 10], when traversing to nums1 [2] and nums2 [2], element 5 and element 9 are not At this time, we are sure that the two elements currently traversed are definitely not part of the longest common subsequence, so we exclude them. However, dp(3,3) must have a value, because this is a recursion, starting from the bottom Recursively to the upper layer, so the value of dp(3,3) at this time is dp(i-1, j) or dp(i, j-1), whichever is longer.

I first use the recursive method to solve this problem. If I did not write clearly or write something wrong, you can comment or send a private message to me.

/**
  * 递归方法实现
  */
public class LCS {

	public static void main(String[] args) {
		int[] nums1 = {1,3,4,10};
		int[] nums2 = {1,2,3,4,10,11};
		System.out.println(lcs(nums1, nums2));
	}
    
	static int lcs(int[] nums1, int[] nums2) {
		if(nums1 == null || nums1.length == 0) return 0;
		if(nums2 == null || nums2.length == 0) return 0;
		//递归调用
		return lcs1(nums1 , nums1.length,nums2,nums2.length);
	}
	
	static int lcs1(int[] nums1 , int i, int[] nums2,int j) {
		//因为当i或者j等于0,说明已经某一个数组已经比较完了
		if(i == 0 || j == 0) return 0;	//递归基,也就是递归什么时候结束的条件
		//递归调用
		//这里类似于dp(i,j) = max{dp(i - 1,j),dp(i,j - 1)}
		if(nums1[i - 1] != nums2[j - 1]) return Math.max(lcs1(nums1, i - 1, nums2, j), lcs1(nums1, i, nums2, j - 1));
        //这里类似于dp(i,j) = dp(i - 1,j - 1) + 1
		return lcs1(nums1,i - 1,nums2,j - 1) + 1;
	}
}

Use dynamic programming to solve this problem. If I don’t write clearly or write something wrong, you can comment or send a private message to me.

public class LCS {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] nums1 = {1,3,4,10};
		int[] nums2 = {1,2,3,4,10,11};
		System.out.println(lcs(nums1, nums2));
	}

    static int lcs(int[] nums1, int[] nums2) {
		if(nums1 == null || nums1.length == 0) return 0;
		if(nums2 == null || nums2.length == 0) return 0;
		int[][] dp = new int[nums1.length + 1][nums2.length + 1];
		//遍历二维数组
		for (int i = 1; i <= nums1.length; i++) {
			for (int j = 1; j <= nums2.length; j++) {
				if(nums1[i - 1] == nums2[j - 1]) {	//如果元素相等,就把前面的最长公共子序列 的个数  + 1,因为相当于把这个元素拼接在后面
					dp[i][j] = dp[i - 1][j - 1] + 1;	
				}else {
					//如果元素不相等,就当前的元素传进把前面的最长公共子序列,看能不能拼接出更长的公共子序列
					dp[i][j] = Math.max(dp[i - 1][j],dp[i][j - 1]);
				}
			}
		}
		return dp[nums1.length][nums2.length];
	}
}

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/114883828