LeetCode 雙指標+hash表方法
阿新 • • 發佈:2019-01-24
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;