动态规划-java

这篇博客探讨了两种算法问题:一是如何找到两个字符串的最长公共子串,通过建立二维矩阵并优化查找过程;二是解决数组中连续子数组的最大和,通过动态规划实现。文章提供了详细的算法思路、代码实现及优化方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一求两个字符串的最长公共子串

牛客:https://www.nowcoder.com/practice/f33f5adc55f444baa0e0ca87ad8a6aac?tpId=117&&tqId=35268&rp=1&ru=/ta/job-code-high&qru=/ta/job-code-high/question-ranking

参考:https://blog.csdn.net/qq_25800311/article/details/81607168

问题:有两个字符串str和str2,求出两个字符串中最长公共子串长度。

比如:str=acbcbcef,str2=abcbced,则str和str2的最长公共子串为bcbce,最长公共子串长度为5。

算法思路:

1、把两个字符串分别以行和列组成一个二维矩阵。

2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。

3、通过查找出值为1的最长对角线就能找到最长公共子串。

针对于上面的两个字符串我们可以得到的二维矩阵如下:

从上图可以看到,str1和str2共有5个公共子串,但最长的公共子串长度为5。

为了进一步优化算法的效率,我们可以再计算某个二维矩阵的值的时候顺便计算出来当前最长的公共子串的长度,即某个二维矩阵元素的值由record[i][j]=1演变为record[i][j]=1 +record[i-1][j-1],这样就避免了后续查找对角线长度的操作了。修改后的二维矩阵如下

java代码:

创建二维数组int[][] result = new int[a.length + 1][b.length + 1],int[i][j]表示当前最长的公共子串长度。

import java.util.*;


public class Solution {
    /**
     * longest common substring
     * @param str1 string字符串 the string
     * @param str2 string字符串 the string
     * @return string字符串
     */
    public String LCS (String str1, String str2) {
        // write code here
        char[] a = str1.toCharArray();
        char[] b = str2.toCharArray();
        int index = 0;
        int[][] result = new int[a.length + 1][b.length + 1];
        int max = 0;
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b.length; j++) {
                if (a[i] == b[j]) {
                    result[i + 1][j + 1] = result[i][j] + 1;
                    if (max < result[i + 1][j + 1]) {
                        max = result[i + 1][j + 1];
                        index = j + 1;
                    }
                }
            }
        }
        if (max == 0) {
            return "-1";
        }
        return str2.substring(index - max, index);
    }
}

连续子数组的最大和

力扣https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/

我写的解法:空间复杂度没通过。。。

public static int maxSubArray(int[] nums) {
		if (nums.length == 0 || nums == null) {
			return 0;
		}
		int[][] dp = new int[nums.length][nums.length];
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < nums.length - i; j++) {

				for (int k = 0; k <= j; k++) {
					dp[i][j] += nums[i + k];
				}
				if (dp[i][j] > max) {
					max = dp[i][j];
				}
			}
		}
		return max;
	}

答案二

dp数组的含义: dp[i] 为以num[i] 结尾的最大连续子串和
边界条件: dp[0] = nums[0]
动态转移方程:

若 dp[i − 1] ≤ 0,说明 dp[i - 1] 对 dp[i] 产生负贡献,即 dp[i-1] + nums[i] 还不如 nums[i] 本身大,所以dp[i] = nums[i]
若 dp[i − 1] > 0, dp[i] = dp[i-1] + nums[i]

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        dp[0] = nums[0];
        int max = nums[0];
        for(int i = 1; i < n; i++) {
        	// dp[i] = Math.max(dp[i- 1] + nums[i], nums[i]);	
            dp[i] = dp[i - 1] <= 0 ? nums[i] : nums[i] + dp[i - 1];
            max = Math.max(max, dp[i]);
        }
        return max;
    }
}
优化:dp[i] 只与 dp[i - 1] 有关,所以可以只用sum一个变量来记录,当sum < 0时,不管下一个num是正是负,sum + num都会更小,所以这是令sum = num


class Solution {
    public int maxSubArray(int[] nums) {
        int ans = nums[0];
        int sum = 0;
        for(int num: nums) {
            if(sum > 0) {
                sum += num;
            }else{
                sum = num;
            }
            ans = Math.max(ans, sum);
        }
        return ans;
    }
}

作者:Sophia_fez
链接:https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/solution/dong-tai-gui-hua-by-sophia_fez/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三最大递增子序列

https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值