最大子串和问题最小子串覆盖问题

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. 最长子串不重复问题(中等)

[LintCode] 最小子串覆盖 Java

最小子串覆盖 · Minimum Window Substring

32 最小子串覆盖