Lintcode 32 Minimum Window Substring

题目描述

Description
Given a string source and a string target, find the minimum window in source which will contain all the characters in target.

  • If there is no such window in source that covers all characters in target, return the emtpy string “”.
  • If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in source.
  • The target string may contain duplicate characters, the minimum window should cover all characters including the duplicate characters in target.

Clarification
Should the characters in minimum window has the same order in target?

  • Not necessary.

Example
For source = “ADOBECODEBANC”, target = “ABC”, the minimum window is “BANC”

Challenge
Can you do it in time complexity O(n) ?
题目意思是给定字符串source和目标字符串target,在字符串source中找到包括所有目标字符串字母的最小子串。

思路

刚开始我想用循环来扫描,然后用replacefirst来替换掉重复的(可能难以表述清楚),不过这样也做出来了,不过明显不好理解,所以就换了一种方法写(最开始的代码后面也会贴出来)
之后呢,思考了下,认为用hashmap来做会比较方便,而且便于理解,大致思路如下
用一个HashMap<Character, Integer>来存放每个字符,key是字符,value值为map中字符的个数

  • 首先将target字符串中每个字符存放进map里面
for (int i = 0; i < tSize; i++) {
            char c = target.charAt(i);
            if (map.containsKey(c)) {
                map.put(c, map.get(c) + 1);
            } else {
                map.put(c, 1);
            }
        }
  • 之后循环找到符合条件的字符串(包含目标字符串中所有字符的字符串)
while (j < sSize && n < tSize) {
                    char c = source.charAt(j);
                    if (map.containsKey(c)) {
                        if (map.get(c) > 0) {
                            n++;
                        }
                        map.put(c, map.get(c) - 1);
                    }
                    j++;
                }
  • 然后再根据字符串长度来替换result字符串(最终字符串)
if (n == tSize && min > j - i) {
                    min = j - i;
                    result = source.substring(i, j);
                }
  • 最后再判断是否要将字符放回去
char c = source.charAt(i);
                if (map.containsKey(c)) {
                    if (map.get(c) >= 0) {
                        n--;
                    }
                    map.put(c, map.get(c) + 1);
                }

代码

  • 最开始的解法
public class Solution {
    /**
     * @param source : A string
     * @param target: A string
     * @return: A string denote the minimum window, return "" if there is no such a string
     */
    public String minWindow(String source, String target) {
        // write your code here
        if (source.length() == 0 || target.length() == 0) {
            return source;
        }
        String str;
        int min = source.length();
        int start = 0, end = 0;
        int ssize = source.length() - target.length() + 1;
        for (int i = 0; i < ssize; i++) {
            String t = target;
            str = "";
            if (t.contains(String.valueOf(source.charAt(i)))) {
                for (int j = i; j < min + i && j < source.length(); j++) {
                    String temp = String.valueOf(source.charAt(j));
                    if (t.contains(temp)) {
                        str += temp;
                        if ("*&^%$#@!():".contains(temp)) {
                            temp = "//" + temp;
                        }
                        t = t.replaceFirst(temp,"");
                    }
                    if (str.length() == target.length() && min >= j - i + 1) {
                        min = j - i + 1;
                        start = i;
                        end = j + 1;
                        break;
                    }
                }
            }
        }
        return source.substring(start, end);
    }
}
  • hashmap解法
public String minWindow(String source, String target) {
        // write your code here
        //第一种解法用hashmap
        HashMap<Character, Integer> map = new HashMap<>();
        int tSize = target.length();
        int sSize = source.length();
        //将target字符串中所有的字符放入map中
        for (int i = 0; i < tSize; i++) {
            char c = target.charAt(i);
            if (map.containsKey(c)) {
                map.put(c, map.get(c) + 1);
            } else {
                map.put(c, 1);
            }
        }
        String result = "";
        int min = Integer.MAX_VALUE;
        int n = 0, j = 0;
        for (int i = 0; i < sSize; i++) {
            if (map.containsKey(source.charAt(i))) {
                //找到符合条件的子串
                while (j < sSize && n < tSize) {
                    char c = source.charAt(j);
                    if (map.containsKey(c)) {
                        if (map.get(c) > 0) {
                            n++;
                        }
                        map.put(c, map.get(c) - 1);
                    }
                    j++;
                }
                //替换result
                if (n == tSize && min > j - i) {
                    min = j - i;
                    result = source.substring(i, j);
                }
                //判断是否要将第一个字符重新放回map中
                char c = source.charAt(i);
                if (map.containsKey(c)) {
                    if (map.get(c) >= 0) {
                        n--;
                    }
                    map.put(c, map.get(c) + 1);
                }
            }
        }
        return result;
    }

还有一种解法,是不用hashmap的,而是用大小为256(正好对应char字符)数组储存字符,大体思路差不多,这个更好理解吧

  • 不用hashmap的解法
public String minWindow(String source, String target) {
        // write your code here
        //第二种解法不用hashmap
        int tSize = target.length();
        int sSize = source.length();
        //将target里面的每个字符放入数组中
        for (int i = 0; i < tSize; i++) {
            chars[target.charAt(i)]++;
        }
        String result = "";
        int j = 0, min = Integer.MAX_VALUE;
        for (int i = 0; i < sSize; i++) {
            while (j < sSize && !isFindAll()) {
                chars[source.charAt(j)]--;
                j++;
            }
            if (isFindAll() && j - i < min) {
                min = j - i;
                result = source.substring(i, j);
            }
            chars[source.charAt(i)]++;
        }
        return result;
    }

    //判断是否所有字符都被寻找到了
    private boolean isFindAll() {
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] > 0) {
                return false;
            }
        }
        return true;
    }

猜你喜欢

转载自blog.csdn.net/qq_35464543/article/details/82953043
今日推荐