Sunday, September 17, 2017

392. Is Subsequence

二刷 08/2022
Version #1 Two Pointers
写了一个bug就是当while循环过了之后只是表示有可能有match的character,ti需要继续加1,否则会发生同样的character重复match
Time O(T) - length of the target string
Space O(1)
Runtime: 4 ms, faster than 11.01% of Java online submissions for Is Subsequence.
Memory Usage: 41.9 MB, less than 66.53% of Java online submissions for Is Subsequence.
class Solution {
    public boolean isSubsequence(String s, String t) {
        int ti = 0;
        int si = 0;
        for (si = 0; si < s.length(); si++) {
            while (ti < t.length() && s.charAt(si) != t.charAt(ti)) {
                ti++;
            }
            if (ti == t.length()) {
                break;
            }
            ti++;
        }
        return si == s.length();
    }
}

Version #2 Binary Search for follow up
Time O(T) + O(SlogT) for each input S
Space O(T)
Runtime: 9 ms, faster than 5.74% of Java online submissions for Is Subsequence.
Memory Usage: 43.5 MB, less than 5.13% of Java online submissions for Is Subsequence.
class Solution {
    public boolean isSubsequence(String s, String t) {
        Map<Character, List<Integer>> indices = new HashMap<>();
        for (int i = 0; i < t.length(); i++) {
            char tc = t.charAt(i);
            indices.putIfAbsent(tc, new ArrayList<>());
            indices.get(tc).add(i);
        }
        int ti = 0;
        for (int i = 0; i < s.length(); i++) {
            int ni = search(indices.getOrDefault(s.charAt(i), new ArrayList<>()), ti);
            if (ni == -1) {
                return false;
            }
            ti = ni + 1;
        }
        return true;
    }
    // find the first index larger than or equals to target
    private int search(List<Integer> indices, int target) {
        if (indices.size() == 0) {
            return -1;
        }
        int start = 0;
        int end = indices.size() - 1;
        while (start < end) {
            int mid = start + (end - start) / 2;
            if (indices.get(mid) >= target) {
                end = mid;
            } else {
                start = mid + 1;
            }
        }
        if (indices.get(start) >= target) {
            return indices.get(start);
        }
        return -1;
        
    }



Version #1 Two Pointers
28.20 %
class Solution {
    public boolean isSubsequence(String s, String t) {
        if (s == null || t == null || t.length() < s.length()) {
            return false;
        }
        int ps = 0;
        int pt = 0;
        for (ps = 0; ps < s.length(); ps++) {
            while (pt < t.length() && t.charAt(pt) != s.charAt(ps)) {
                pt++;
            }
            if (pt == t.length()) {
                return false;
            } else {
                pt++;
            }
        }
        return true;
    }
}

Version #2 Follow Up -> Binary Search
二刷
9.45 %
class Solution {
    public boolean isSubsequence(String s, String t) {
        if (s == null || t == null || s.length() > t.length()) {
            return false;
        }
        Map<Character, List<Integer>> map = init(t);
        return check(s, map);
    }
    // key->char, value->indices of this char
    private Map<Character, List<Integer>> init(String t) {
        Map<Character, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < t.length(); i++) {
            char c = t.charAt(i);
            if (!map.containsKey(c)) {
                map.put(c, new ArrayList<>());
            }
            map.get(c).add(i);
        }
        return map;
    } 
    private boolean check(String s, Map<Character, List<Integer>> map) {
        int curr = 0;
        int length = s.length();
        List<Integer> indices = null;
        for (int i = 0; i < length; i++) {
            indices = map.get(s.charAt(i));
            if (indices == null) {
                return false;
            }
            // find the 1st index larger than or equal to curr
            int start = 0;
            int end = indices.size() - 1;
            while (start < end) {
                int mid = start + (end - start) / 2;
                if (indices.get(mid) < curr) {
                    start = mid + 1;
                } else {
                    end = mid;
                }
            }
            if (indices.get(start) < curr) {
                return false;
            }
            curr = indices.get(start) + 1;
        }
        return true;
    }
}


一刷
14.79 %
Binary Search 还是写的不好
对于找第一个大于pt的index,如果最后停在start == end时候,这个值是有可能小于pt的,所以最后还是需要额外check一下


class Solution {
    public boolean isSubsequence(String s, String t) {
        if (s == null || t == null) return false;
        // public static ArrayList<myObject>[] a = (ArrayList<myObject>[])new ArrayList<?>[2];
        List<Integer>[] map = (ArrayList<Integer>[])new ArrayList<?>[26];
        for (int i = 0; i < t.length(); i++) {
            int index = t.charAt(i) - 'a';
            if (map[index] == null) map[index] = new ArrayList<>();
            map[index].add(i);
        }
   
        //       ps               pt
        // s = " a   b   c", t = " a   h   b  g   d  c"
        int pt = 0;
        for (int ps = 0; ps < s.length(); ps++) {
            if (pt >= t.length()) return false;
            // t doesn't have this character at all
            if (map[s.charAt(ps) - 'a'] == null) return false;
            // Find the 1st index >= ps, if not found, return -1
            int next = binarySearch(pt, map[s.charAt(ps) - 'a']);
            //System.out.println(s.charAt(ps) + " " + next + "pt: " + pt);
            if (next == -1) return false;
            pt = next + 1;
        }
        return true;
    }
    private int binarySearch(int pt, List<Integer> list) {
        int start = 0;
        int end = list.size() - 1;
        // There's no duplicate in list
        while (start < end) {
            int mid = start + (end - start) / 2;
            if (list.get(mid) == pt) return pt;
            if (list.get(mid) < pt) {
                start = mid + 1;
            } else {
                end = mid;
            }
        }
        if (list.get(start) < pt) return -1;
        else return list.get(start) ; // Very important
    }
}

No comments:

Post a Comment