1. 程式人生 > >LeetCode 雙指標+hash表方法

LeetCode 雙指標+hash表方法

hashtable+雙指標視窗法解題思路

//連結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