LeetCode 双指针+hash表方法

来源:互联网 发布:学生空间_七天网络查分 编辑:程序博客网 时间:2024/05/22 19:32

hashtable+双指针窗口法解题思路

最近一直在刷leetcode,发现许多题目解法很相似,如求 findSubstring,minWindow,lengthOfLongestSubstring问题,解法大致都一样都是用滑动窗口的思想,不过滑动的规则没处理好,很容易导致时间复杂度增加;
题目链接:https://leetcode.com/problems/substring-with-concatenation-of-all-words/;
http://oj.leetcode.com/problems/minimum-window-substring/ ;
http://oj.leetcode.com/problems/longest-substring-without-repeating-characters/ ;

//链接1题解public ArrayList<Integer> findSubstring(String S, String[] L) {    // Note: The Solution object is instantiated only once and is reused by each test case.    ArrayList<Integer> res = new ArrayList<Integer>();    if(S==null || S.length()==0 || L==null || L.length==0)        return res;    HashMap<String,Integer> map = new HashMap<String,Integer>();    for(int i=0;i<L.length;i++)    {        if(map.containsKey(L[i]))        {            map.put(L[i],map.get(L[i])+1);        }        else        {            map.put(L[i],1);        }    }    for(int i=0;i<L[0].length();i++)    {        HashMap<String,Integer> curMap = new HashMap<String,Integer>();        int count = 0;        int left = i;        for(int j=i;j<=S.length()-L[0].length();j+=L[0].length())        {            String str = S.substring(j,j+L[0].length());            if(map.containsKey(str))            {                if(curMap.containsKey(str))                    curMap.put(str,curMap.get(str)+1);                else                    curMap.put(str,1);                if(curMap.get(str)<=map.get(str))                    count++;                else                {                    while(curMap.get(str)>map.get(str))                    {                        String temp = S.substring(left,left+L[0].length());                        if(curMap.containsKey(temp))                        {                            curMap.put(temp,curMap.get(temp)-1);                            if(curMap.get(temp)<map.get(temp))                                count--;                        }                        left += L[0].length();                    }                }                if(count == L.length)                {                    res.add(left);                    //if(left<)                    String temp = S.substring(left,left+L[0].length());                    if(curMap.containsKey(temp))                        curMap.put(temp,curMap.get(temp)-1);                    count--;                    left += L[0].length();                }            }            else            {                curMap.clear();                count = 0;                left = j+L[0].length();            }        }    }    return res;}/*复杂付分析:外循环L[0].length()次,内循环n/L[0].length()次,每次访问的字符串的总次数不超过2n此,每个word最多会被窗口两端各访问一次,总的时间复杂度O(n)*/
 public int lengthOfLongestSubstring(String s) {         //双指针+hashtable(int数组实现)         if(s==null||s.equals("")) return 0;         int max=1;         int[] wind=new int[256];         int start=0,end=0;         Arrays.fill(wind, -1);         for(;end<s.length();end++){                if(wind[s.charAt(end)]>=start)                    start=wind[s.charAt(end)]+1;                wind[s.charAt(end)]=end;                max=Math.max(max,end-start+1);             }             return max;    }
public String minWindow(String S, String T) {    if(S==null || S.length()==0)        return "";    HashMap<Character, Integer> map = new HashMap<Character, Integer>();    for(int i=0; i<T.length();i++)    {        if(map.containsKey(T.charAt(i)))        {            map.put(T.charAt(i),map.get(T.charAt(i))+1);        }        else        {            map.put(T.charAt(i),1);        }    }    int left = 0;    int count = 0;    int minLen = S.length()+1;    int minStart = 0;    for(int right=0; right<S.length();right++)    {        if(map.containsKey(S.charAt(right)))        {            map.put(S.charAt(right),map.get(S.charAt(right))-1);            if(map.get(S.charAt(right))>=0)            {                count++;            }            while(count == T.length())            {                if(right-left+1<minLen)                {                    minLen = right-left+1;                    minStart = left;                                    }                if(map.containsKey(S.charAt(left)))                {                    map.put(S.charAt(left), map.get(S.charAt(left))+1);                    if(map.get(S.charAt(left))>0)                    {                        count--;                    }                }                left++;            }        }    }    if(minLen>S.length())    {        return "";    }    return S.substring(minStart,minStart+minLen);}

关键点分析:
1,窗口左右端什么时候移,每次移动多少距离;
2,窗口内包含的字符序列是否符合要求;一般做法:将题目要求序列放入hashmap或字符数组中,然后遍历字符串的过程中碰到指定字符进行计数count,同时对hashmap进行增减处理,当count符合要求序列长度时停止;然后移动窗口,开始新的循环;左端移动时,对hashmap对应value进行加一处理,右端移动对hashmap对应value进行减一处理;
参考:
http://blog.csdn.net/linhuanmars/article/details/20343903;

0 0
原创粉丝点击