最大子串和问题最小子串覆盖问题
Posted Dream_it_possible!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大子串和问题最小子串覆盖问题相关的知识,希望对你有一定的参考价值。
目录
最大子串和问题
题目
给定一个整数数组,求出数组中最大的子串和。
例如: 2, -1, 3, 5, 6, -3
最大子串和为: 2-1+3+5+6=15
思路一
采用暴力循环的方式,找出每趟最大的子串和,然后再比较每趟的值,最大的那个值即为最大子串和。
完整代码:
private static Integer findMaxSumStrOne(int[] arr) {
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
int temp = arr[i];
int iMax = temp;
for (int j = i + 1; j < arr.length; j++) {
int current = temp + arr[j];
if (current > iMax) {
iMax = current;
}
temp = current;
}
if (iMax > max) {
max = iMax;
}
}
return max;
}
此方法虽然能求解,但是时间复杂度为0(n2), 效率比较低。
思路二
采用淘汰的思想,淘汰掉负贡献的子串,累加正贡献的子串,因为数组中负数会给子串的值变小。
累加后面对子串有贡献的数,如果当前数是负数, 包含2种情况:
1) 如果之前的子串和结果是正数,得到的和是也是正数,那么可以继续累加。
2) 如果之前的子串和结果是负数,那么比较当前数与之前的子串和的大小,如果当前数大于子串和,那么将当前数重新赋值给最大子串和值。
private static Integer findMaxSumStr(int[] arr) {
int sum = arr[0];
int max = sum;
for (int i = 1; i < arr.length; i++) {
if (sum > 0) {
sum += arr[i];
} else {
sum = arr[i];
}
if (max < sum) {
max = sum;
}
}
return max;
}
此方法只需要一个for循环就能实现,时间复杂度为o(n)。
打印结果:
最小子串覆盖问题
题目
给定一个字符串S,字符串T, 求字符串S包含字符串T的最短子串。
例如: S="ADOBECODEBANC", T="ABC"
输出结果: "BANC"
思路一
使用暴力破解的方法
采用顺序字符串的格式获取源字符串的子串,然后用源字符串的子串对目标字符串进行逐个匹配,命中一个字符将目标字符串把该字符给剔除掉,直到目标字符串里的字符全部剔除完毕,就表示找到合适的字符串。
每次找到符合要求的子串(Target)时,比较foundStr和符合要求的Target串的长度,如果长度比源串长度小,就把目标串赋值给foundStr,最终返回结果即可。
也可以根据下标的差值来比较,取差值最小的那个即可。
private static String findStr(String sourceStr, String subStr) {
boolean found = false;
String foundStr = sourceStr;
for (int i = 0; i < sourceStr.length(); i++) {
String source = sourceStr.charAt(i) + "";
String target = subStr;
int index = subStr.indexOf(source);
if (index != -1) {
target = target.substring(0, index) + target.substring(index + 1);
// 目标的子串包含了一个才进行匹配
for (int j = i + 1; j < sourceStr.length(); j++) {
String sub = sourceStr.charAt(j) + "";
// subStr字符串中的所有字符必须全部命中
int subIndex = target.indexOf(sub);
if (subIndex != -1) {
target = target.substring(0, subIndex) + target.substring(subIndex + 1);
if (target.length() == 0) {
System.out.println("符合要求:(" + i + "," + j + ")");
found = true;
String t = sourceStr.substring(i, j + 1);
if (t.length() < foundStr.length()) {
foundStr = t;
}
}
}
}
}
}
if (!found) {
throw new RuntimeException("未找到符合要求的子串!");
}
return foundStr;
}
打印结果:
输入: S= "CQDBANC", T="ABC"
输出: BANC
此方法虽然可行,但是时间复杂度是o(n2), 效率比较低。
以上是关于最大子串和问题最小子串覆盖问题的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode53.最大子串和(简单)76.最小子串覆盖(困难)3. 最长子串不重复问题(中等)
Leetcode53.最大子串和(简单)76.最小子串覆盖(困难)3. 最长子串不重复问题(中等)
Leetcode53.最大子串和(简单)76.最小子串覆盖(困难)3. 最长子串不重复问题(中等)