All Anagrams

Find all occurrence of anagrams of a given string s in a given string l. Return the list of starting indices.

Assumptions

  • sh is not null or empty.

  • lo is not null.

Examples

  • l = "abcbac", s = "ab", return [0, 3] since the substring with length 2 starting from index 0/3 are all anagrams of "ab" ("ab", "ba").

Solution: HashMap + sliding window

size of window = size of target string

use hashmap to track chars in target string. If both found, add starting index to result

public class Solution {
  public List<Integer> allAnagrams(String sh, String lo) {
    List<Integer> result = new ArrayList<>();
    if (lo.length() == 0) return result;
    if (sh.length() > lo.length()) return result;
    
    //count amount of each char in shorter string
    Map<Character, Integer> map = countMap(sh); 
    
    //track number of target chars found
    int match = 0; 
    
    for (int i = 0; i < lo.length(); i++){
      char tmp = lo.charAt(i);
      Integer count = map.get(tmp);
      
      //if char in target string
      if (count != null){
        map.put(tmp, count - 1);
        
        //if first sighting, dedup
        if (count == 1){
          match++;
        }
      }
      
      //add char exiting window back
      if (i >= sh.length()){
        
        //char to add back
        tmp = lo.charAt(i - sh.length());
        count = map.get(tmp);
        
        //if in target string
        if (count != null){
        
          //dedup, negative if adajacent target chars
          //ex: "aa" for target "ab"
          //count would be -1
          
          //char only exiting window if only one left in window
          //aka count == 0
          if (count == 0){
            match--;
          }
          map.put(tmp,count + 1);
        }
      }

      if (match == map.size()){
        result.add(i - sh.length() + 1);
      }
    }
    return result;
  }

  private Map<Character, Integer> countMap(String s){
    Map<Character, Integer> map = new HashMap<>();
    for (char ch: s.toCharArray()){
      Integer count = map.get(ch);
      if (count == null){
        map.put(ch, 1);
      } else {
        map.put(ch, count + 1);
      }
    }
    return map;
  }
}

Last updated

Was this helpful?