Saturday, March 25, 2017

Day 136, 380, Insert Delete GetRandom O(1)

380. Insert Delete GetRandom O(1)
Design a data structure that supports all following operations in average O(1) time.
  1. insert(val): Inserts an item val to the set if not already present.
  2. remove(val): Removes an item val from the set if present.
  3. getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.
class RandomizedSet {
    private static Random random = new Random();
    private List<Integer> list;
    private Map<Integer, Integer> map;
    private int size;
    /** Initialize your data structure here. */
    public RandomizedSet() {
        size = 0;
        list = new ArrayList<>();
        map = new HashMap<>();
    }
    
    /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
    public boolean insert(int val) {
        if (map.containsKey(val)) return false;
        map.put(val, size);
        if (list.size() == size) {
            list.add(size, val);   
        }else {
            list.set(size, val);
        }
        size++;
        
        return true;
    }
    
    /** Removes a value from the set. Returns true if the set contained the specified element. */
    public boolean remove(int val) {
        if (!map.containsKey(val)) return false;
        
        int pos = map.get(val);
        int value = list.get(size - 1);
        list.set(pos, value);
        map.put(value, pos);
        size--;
        map.remove(val);
        
        return true;
    }
    
    /** Get a random element from the set. */
    public int getRandom() {
        return list.get(random.nextInt(size));
    }
}

/**
 * Your RandomizedSet object will be instantiated and called as such:
 * RandomizedSet obj = new RandomizedSet();
 * boolean param_1 = obj.insert(val);
 * boolean param_2 = obj.remove(val);
 * int param_3 = obj.getRandom();
 */

Follow up: duplicates are allowed.
Use Set as values in the map

Saturday, March 18, 2017

Day 135, 532, 438, 387, 459, K-diff Pairs in an Array, Find All Anagrams in a String, First Unique Character in a String, Repeated Substring Pattern

532. K-diff Pairs in an Array
Given an array of integers and an integer k, you need to find the number of unique k-diff pairs in the array. Here a k-diff pair is defined as an integer pair (i, j), where i and j are both numbers in the array and their absolute difference is k.
Example 1:
Input: [3, 1, 4, 1, 5], k = 2
Output: 2
Explanation: There are two 2-diff pairs in the array, (1, 3) and (3, 5).
Although we have two 1s in the input, we should only return the number of unique pairs.
Example 2:
Input:[1, 2, 3, 4, 5], k = 1
Output: 4
Explanation: There are four 1-diff pairs in the array, (1, 2), (2, 3), (3, 4) and (4, 5).
Example 3:
Input: [1, 3, 1, 5, 4], k = 0
Output: 1
Explanation: There is one 0-diff pair in the array, (1, 1).
Note:
  1. The pairs (i, j) and (j, i) count as the same pair.
  2. The length of the array won't exceed 10,000.
  3. All the integers in the given input belong to the range: [-1e7, 1e7].
public class Solution {
    public int findPairs(int[] nums, int k) {
        if (k < 0) return 0;
        
        Set<Integer> set = new HashSet<>();
        Set<Integer> firtInPair = new HashSet<>();
        
        for (int i = 0; i < nums.length; i++) {
            int cur = nums[i];
            if (set.contains(cur + k)) {
                firstInPair.add(cur);
            }
            if (set.contains(cur - k)) {
                firstInPair.add();
            }
            set.add(cur);
        }
        
        return cur.size();
    }
}


438. Find All Anagrams in a String
Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
The order of output does not matter.
Example 1:
Input:
s: "cbaebabacd" p: "abc"

Output:
[0, 6]

Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input:
s: "abab" p: "ab"

Output:
[0, 1, 2]

Explanation:
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab".
Sliding window
另一种写法是用array[256]来代替Map,代码会更简洁。因为array[char] == 0可以同时代表没有出现过的char和已经用完的char
public class Solution {
    public List findAnagrams(String s, String p) {
        Map occurance = getOccurance(p);
        return findIndexes(s, p.length(), occurance, new HashMap<>(occurance));
    }
    
    private Map getOccurance(String p) {
        Map occ = new HashMap<>();
        
        for (int i = 0; i < p.length(); i++) {
            char c = p.charAt(i);
            if (occ.containsKey(c)) {
                occ.put(c, occ.get(c) + 1);
            } else {
              occ.put(c, 1);  
            }
        }
        
        return occ;
    }
    
    private List findIndexes(String s, int count, Map occ, Map backup) {
        
        List rt = new ArrayList<>();
        int start = 0;
        for (int i = 0; i < s.length(); i++) {
            char c =s.charAt(i);
            if (!occ.containsKey(c)) {
                // reset
                occ = new HashMap<>(backup);
                start = i + 1;
                count = occ.size();
                continue;
            }
            
            while (occ.get(c) == 0) {
                occ.put(s.charAt(start), occ.get(s.charAt(start)) + 1);
                start++;
                count++;
            }
            
            count--;
            if (count == 0) {
                rt.add(start);
            }
            occ.put(c, occ.get(c) - 1);
        }
        
        return rt;
    }
}
387. First Unique Character in a String
Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1.
Examples:
s = "leetcode"
return 0.

s = "loveleetcode",
return 2.

Note: You may assume the string contain only lowercase letters.
public class Solution {
    public int firstUniqChar(String s) {
        int occ[] = new int[256];
        
        for (int i = 0; i < s.length(); i++) {
            int val = s.charAt(i) - '0';
            occ[val]++;
        }
        
        for (int i = 0; i < s.length(); i++) {
            int val = s.charAt(i) - '0';
            if (occ[val] == 1) {
                return i;
            }
        }
        
        return -1;
    }
}
459. Repeated Substring Pattern
Given a non-empty string check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. You may assume the given string consists of lowercase English letters only and its length will not exceed 10000.
Example 1:
Input: "abab"

Output: True

Explanation: It's the substring "ab" twice.
Example 2:
Input: "aba"

Output: False
Example 3:
Input: "abcabcabcabc"

Output: True

Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.)
可以用KMP
以下方法可以稍微再简化:inner loop里可以把所有的substring加起来然后跟原来的比较
public class Solution {
    public boolean repeatedSubstringPattern(String s) {
        
        for (int i = 0; i < s.length() / 2; i++) {
            if (s.length() % (i + 1) != 0) {
                continue;
            }
            
            String sub = s.substring(0, i + 1);
            boolean flag = true;
            for (int j = i + 1; j < s.length() - i; j += i + 1) {
                String secSub = s.substring(j, j + i + 1);
                if (!secSub.equals(sub)) {
                    flag = false;
                    break;
                }
            }
            if (flag == true) return true;
        }
        
        return false;
    }
}