Skip to content

Latest commit

 

History

History
807 lines (585 loc) · 18.1 KB

Problems.md

File metadata and controls

807 lines (585 loc) · 18.1 KB

Problems

Solution

// TODO

Arrays And Strings

Solution

public int lengthOfLongestSubstring(String s) {
    if(s == null || s.isEmpty()) return 0;

    Set<Character> set = new HashSet<>();

    int max = 1;
    set.add(s.charAt(0));
    int start=0;
    for(int i=1; i < s.length(); i++){
        if(set.contains(s.charAt(i))){
            while(s.charAt(start) != s.charAt(i)){
                set.remove(s.charAt(start));
                start++;
            }
            start++;
        }else{
            set.add(s.charAt(i));
        }
        max = Math.max(max, i-start+1);
    }
    return max;
}

Solution

public boolean isMatch(String text, String pattern) {
    if (pattern.isEmpty()) return text.isEmpty();
    boolean first_match = (!text.isEmpty() &&
                            (pattern.charAt(0) == text.charAt(0) || pattern.charAt(0) == '.'));

    if (pattern.length() >= 2 && pattern.charAt(1) == '*'){
        return (isMatch(text, pattern.substring(2)) ||
                (first_match && isMatch(text.substring(1), pattern)));
    } else {
        return first_match && isMatch(text.substring(1), pattern.substring(1));
    }
}

  • Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
  • Your algorithm should run in O(n) complexity.
Solution

public int longestConsecutive(int[] nums) {
   if (nums.length < 2) return nums.length;

    int max = 0;
    Set<Integer> set = new HashSet<>();
    Arrays.stream(nums).forEach(num -> set.add(num));

    for (int i = 0; i < nums.length; i++){
        if (!set.contains(nums[i] - 1)){
            int next = nums[i] + 1;
            int curLen = 1;
            while (set.contains(next)){
                curLen++;
                next++;
            }
            max = Math.max(curLen, max);
        }
    }
    return max;
}

  • O(n) time and O(1) space.
Solution

public int firstMissingPositive(int[] nums) {

    for(int i=0; i < nums.length; i++)
        if(nums[i] < 0)
            nums[i] = 0;

    for(int i=0; i < nums.length; i++){
        int n = Math.abs(nums[i]) - 1;

        if(n >= 0 && n < nums.length && nums[n] >= 0)
            nums[n] = nums[n] == 0 ? -1 * nums.length : -1 * nums[n];
    }

    for(int i=0; i < nums.length; i++)
        if(nums[i] >= 0)
            return i+1;

    return nums.length+1;
}

Solution

// TODO

Solution

public int longestOnes(int[] A, int K) {

    int max = 0;

    for(int lo=0, hi=0; hi < A.length; hi++){
        if(A[hi] == 0 && K > 0){
            K--;
        }else if(A[hi] == 0 && K == 0){
            while(K == 0 && lo < A.length){
                if(A[lo] == 0){
                    K++;
                }
                lo++;
            }
            K--;
        }

        max = Math.max(max, hi+1 - lo);
    }

    return max;
}

Solution

public int characterReplacement(String s, int k) {

        int[] count = new int[26];
        int res = 0;

        int max = 0;
        for(int lo=0, hi=0; hi < s.length(); hi++){
            max = Math.max(max, ++count[s.charAt(hi) - 'A']);
            if(hi - lo + 1 - max > k){
                count[s.charAt(lo) - 'A']--;
                lo++;
            }
            res = Math.max(res, hi - lo + 1);
        }

        return res;
    }

Linked Lists

Tree & Graphs

  • In DFS, if you find p and q at the same time, move this parent node up, otherwise move p or q up.
Solution

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
{
    if (root == null) return null;

    if (root == p || root == q){
        return root;
    }

    TreeNode left_lca = lowestCommonAncestor(root.left, p, q);
    TreeNode right_lca = lowestCommonAncestor(root.right, p, q);

    if (left_lca != null && right_lca != null){
        return root;
    }
    if (left_lca != null){
        return left_lca;
    }
    else{
        return right_lca;
    }
}

  • Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.
  • Calling next() will return the next smallest number in the BST.
Solution

class BSTIterator {

    private Stack<TreeNode> s = new Stack<>();

    public BSTIterator(TreeNode root) {
        while(root != null){
            s.push(root);
            root = root.left;
        }
    }

    /** @return the next smallest number */
    public int next() {
        TreeNode last = s.pop();

        TreeNode node = last.right;
        while(node != null){
            s.push(node);
            node = node.left;
        }

        return last.val;
    }

    /** @return whether we have a next smallest number */
    public boolean hasNext() {
        return !s.isEmpty();
    }
}

Solution

// TODO

Solution

// TODO

Solution

public void flatten(TreeNode root) {
    flat(root);
}
private TreeNode flat(TreeNode node){
    if(node == null) return null;

    TreeNode left = node.left;
    TreeNode right = node.right;

    TreeNode last = node;
    if(left != null){
        node.right = left;
        last = flat(left);
    }
    if(right != null){
        last.right = right;
        last = flat(right);
    }

    node.left = null;
    return last;
}

Solution

public class NestedIterator implements Iterator<Integer> {

    Stack<NestedInteger> stack = new Stack<>();

    public NestedIterator(List<NestedInteger> nestedList) {
        for(int i = nestedList.size() - 1; i >= 0; i--) {
            stack.push(nestedList.get(i));
        }
    }

    @Override
    public Integer next() {
        return stack.pop().getInteger();
    }

    @Override
    public boolean hasNext() {
        while(!stack.isEmpty()) {
            NestedInteger curr = stack.peek();
            if(curr.isInteger()) {
                return true;
            }
            stack.pop();
            for(int i = curr.getList().size() - 1; i >= 0; i--) {
                stack.push(curr.getList().get(i));
            }
        }
        return false;
    }
}

Backtracking

Solution

public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> list = new ArrayList<>();
        // Arrays.sort(nums);
        backtrack(list, nums, new ArrayList<Integer>(), 0);
        return list;
    }

    private void backtrack(List<List<Integer>> list, int[] nums, List<Integer> tempList, int start){
        list.add(new ArrayList(tempList));
        for(int i=start; i < nums.length; i++){
            tempList.add(nums[i]);
            backtrack(list, nums, tempList, i+1);
            tempList.remove(tempList.size()-1);   
        }
    }

Solution

// TODO

Solution

// TODO

Solution

// TODO

Solution

// TODO

Solution

// TODO

Solution

// TODO

Solution

public List<List<String>> partition(String s) {
    List<List<String>> list = new ArrayList<>();
    backtrack(s, new ArrayList<String>(), list);
    return list;
}

private void backtrack(String s, List<String> temp, List<List<String>> list){
    if(s.isEmpty()){
        list.add(new ArrayList<String>(temp));
    }

    for(int i=0; i < s.length(); i++){
        String str = s.substring(0,i+1);
        String revStr = new StringBuilder(str).reverse().toString();
        if(str.equals(revStr)){
            temp.add(str);
            backtrack(s.substring(i+1), temp, list);
            temp.remove(temp.size()-1);
        }
    }
}

Sorting and Searching

  • When you find middle, one of the sides will be sorted already, check if target values is in that sorted range, otherwise continue with other side.
Solution

public int search(int[] nums, int target) {

    int start=0;
    int end=nums.length-1;

    while(start <= end){
        int mid = (start+end)/2;

        if(nums[mid] == target){
            return mid;
        }

        if (nums[start] <= nums[mid]){
                if (target < nums[mid] && target >= nums[start]){
                    end = mid - 1;
                }else{
                    start = mid + 1; 
                }
        } 
        if (nums[mid] <= nums[end]){
            if (target > nums[mid] && target <= nums[end]){
                start = mid + 1;
            }else{
                end = mid - 1;
            }
        }
    }
    return -1;
}

  • Search in Rotated Sorted Array + allows duplicates
Solution

public boolean search(int[] nums, int target) {

    int start=0;
    int end=nums.length-1;

    while(start <= end){
        int mid = (start+end)/2;

        if(nums[mid] == target){
            return true;
        }

        if (nums[mid] == nums[start]) {
            start++;
        }else if (nums[start] <= nums[mid]){
            if (target < nums[mid] && target >= nums[start]){
                    end = mid - 1;
            }else{
                start = mid + 1;
            }
        }
        else if (nums[mid] <= nums[end]){
            if (target > nums[mid] && target <= nums[end]){
                start = mid + 1;
            }else{
                end = mid - 1;
            }
        }
    }
    return false;

Solution

public List<Interval> merge(List<Interval> intervals) {
    if(intervals.isEmpty()) return new ArrayList<Interval>();

    Stack<Interval> s = new Stack();
    Collections.sort(intervals, (a,b) -> (a.start == b.start) ? a.end - b.end : a.start - b.start);

    Iterator<Interval> it = intervals.iterator();
    s.push(it.next());
    while(it.hasNext()){
        Interval curr = it.next();
        Interval last = s.peek();

        if(last.end >= curr.start){
            s.pop();
            s.push(new Interval(last.start, Math.max(curr.end, last.end)));
        }else{
            s.push(curr);
        }
    }
    return new ArrayList<Interval>(s);
}

Dynamic Programming

  • Kadene's Algorithm
Solution

public int maxSubArray(int[] nums) {
    int max = Integer.MIN_VALUE;
    int subArrayMax = 0;

    for (int i = 0; i < nums.length; i++){
        subArrayMax += nums[i];
        max = Math.max(max, subArrayMax);
        subArrayMax = Math.max(subArrayMax, 0);
    }

    return max;
}

Solution

public int lengthOfLIS(int[] nums) {
    if (nums.length < 2) return nums.length;

    int longestLen = 1;
    int[] dp = new int[nums.length];

    dp[0] = 1;
    for (int i = 0; i < nums.length; i++){
        int maxLen = 0;
        for (int j = 0; j < i; j++){
            if (nums[j] < nums[i]){
                maxLen = Math.max(maxLen, dp[j]);
            }
        }
        dp[i] = maxLen + 1;
        longestLen = Math.max(longestLen, dp[i]);
    }
    return longestLen;
}

  • Sort the array. Ascend on width and descend on height if width are same.
  • Find the longest increasing subsequence based on height
Solution

// TODO

Solution

public int numDecodings(String s) {
    if(s.isEmpty()) return 0;

    int n = s.length();
    int[] dp = new int[n+1];
    dp[n] = 1;

    for(int i=n-1;i>=0;i--) {
        if(s.charAt(i) == '0') 
            dp[i] = 0;
        else {
            dp[i] = dp[i+1];
            if(i < (n-1) && (s.charAt(i) == '1' || s.charAt(i) == '2' && s.charAt(i+1) < '7')) 
                dp[i]+=dp[i+2];
        }
    }

    return dp[0]; 
}

Design

  • Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
Solution

// TODO

  • Design a data structure that supports the following two operations: void addWord(word) and bool search(word)
Solution

class WordDictionary {

    class TrieNode {
        Map<Character, TrieNode> children;
        TrieNode(){
            this.children = new HashMap<Character, TrieNode>();
        }
    }

    TrieNode root;

    public WordDictionary() {
        this.root = new TrieNode();
    }

    public void addWord(String word) {
        word = word + "#";

        TrieNode node = root;
        for(int i=0; i < word.length(); i++){
            node = node.children.computeIfAbsent(word.charAt(i), t -> new TrieNode());
        }  
    }

    public boolean search(String word) {
        return searchNode(word + "#", root);
    }

    private boolean searchNode(String word, TrieNode node) {
        if(word.isEmpty()) return true;

        for(int i=0; i < word.length(); i++){
            if(word.charAt(i) == '.'){
                // search for every children, one true result is enough
                for(TrieNode child : node.children.values()){
                    if(searchNode(word.substring(i+1,word.length()), child))
                        return true;
                }
                // if not found in any children, then return false
                return false;
            }else{
                node = node.children.get(word.charAt(i));
                if(node == null)
                    return false;
            }
        }

        return true;
    }
}

Others

  • Tricky, bool knows(a, b) result of this method eliminates either a or b from celebrity candidate
Solution

public int findCelebrity(int n) {
    int candidate = 0;

    // find celebrity candidate
    for(int i = 1; i < n; i++){
        if(knows(candidate, i)) candidate = i;
    }
    // test candidate -> celebrity or not
    for(int i = 0; i < n; i++){
        if(i != candidate && (knows(candidate, i) || !knows(i, candidate))) return -1;
    }
    return candidate;
}

Solution

// TODO