Midterm Review

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Midterm Exam

Copyright © 直通硅谷

http://www.zhitongguigu.com/

  • 4 questions + 1 bonus question. Finish previous 4 questions first, work on the bonus one if you have time.

  • Time limit is 2 hours, 18:30 - 20:30 PST

  • Copy and paste the NDA above to your txt file and sign. Every candidate should sign the NDA first, if not, the solutions will be regarded as INVALID.

  • All solutions should be replied to govalley.201612@gmail.com

  • All solutions should be submitted in a separate file, named as YourName_midterm.txt.

  • Only one API needs to be implemented for each problem (Java or C++).

  • Comment the ideas and thoughts above your implementation.

  • The submitted TXT file should include NDA, 4 + 1 explanations, complexity & implementations.

Midterm Exam

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Sample:
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc",
s2 = "dbbca",
When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

Q1
/*
the idea is that...

Time: O(n)
Space: O(n)
*/

public boolean isInterleave(String s1, String s2, String s3) {

}

Midterm Review

  • Time Complexity
  • Data Structure
    • Array, Sort
    • LinkedList
    • Stack
    • Queue
    • HashMap
  • Algorithms
    • Binary Search
    • Recursion

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Time Complexity

  • Definition
    •            O
    • Best Case, Average Case, Worst Case
  • How to calculate
    • Master Method
    • Maths Deduction
      • Recursion
    • Solution/Search Space
    • From the code
  • Important Time Complexity
    • Sort: O(nlogn)
    • Binary Search: O(logn)
\Theta
Θ\Theta
\Omega
Ω\Omega

Arrays - add (to end):

- Best: O(1)

- Worst: O(n)

- Average: O(1)

- T(n) = T(n/2) + c = T(n/4) + 2c = .... = T(1) + (logn)*c

- T(n) = T(n-1) + cn = T(n-2) + cn + c(n-1) = ... = T(1) + c(n + (n-1) + ... + 0)

- Combination, Permutation, ...

- Two Pointers 

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Array

  • Definition
    • Same type elements, continuously in memory
    • Get any element in constant time.
  • Basic Operation
    • Get, Add, Remove
  • Implementation
    • capacity v.s. size  -> resize(ensureSize), 
    • Element[] data
  • Two Pointers
    • Use two/multiple pointers to iterate the array
    • Two Sum, Three Sum, Odd Even Sort,  ... 

- Get: O(1)

- Add: O(1), O(n)

- Remove: O(1), O(n)

2Sum -> 3Sum -> 4Sum -> ... -> Combination Sum

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Minimum Size Subarray Sum

Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return 0 instead.

Example Input: [2, 3, 1, 2, 4, 3]; 7

Example Output: 2 ([4, 3])

public int minSubArrayLen(int s, int[] nums) {
    int sum = 0;
    int min_length = Integer.MAX_VALUE;    // Why max?
    for (int start = 0, end = 0; start < nums.length; start++) {
        while (end < nums.length && sum < s) {
            sum += nums[end++];
        }
        if (sum >= s) {
            min_length = Math.min(min_length, end-start);
        }
        sum -= nums[start];
    }
    return min_length == Integer.MAX_VALUE ? 0 : min_length;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC".

Notes:​

- If there is no such window in S that covers all characters in T, return the empty string "".

- You are guaranteed that there will always be only one unique minimum window in S, if exist.

Copyright © 直通硅谷

http://www.zhitongguigu.com/

HashMap Homework

public String minWindow(String s, String t) {
    int[] expected = new int[256];
    int[] visited = new int[256];
    for (int i = 0; i < t.length(); i++) {
        expected[(int)t.charAt(i)]++;
    }
    int end = 0, minLength = Integer.MAX_VALUE, count = 0;
    String result = "";
    for (int start = 0; start < s.length(); start++) {
        while (end < s.length() && count != t.length()) {
            visited[s.charAt(end)]++;
            if (visited[s.charAt(end)] <= expected[s.charAt(end)]) {
                count++;
            }
            end++;
        }
        if (count == t.length()) {
            if (end - start < minLength) {
                minLength = end - start;
                result = s.substring(start, end);
            }
        }
        if (expected[s.charAt(start)] > 0) {
            visited[s.charAt(start)]--;
            if (visited[s.charAt(start)] < expected[s.charAt(start)]) {
                count--;
            }
        }
    }
    return result;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

🤔

public String minWindow(String s, String t) {
    int[] hm = parseToIntArray(t);
    String result = s + t;
    int count = t.length();
    for (int i = 0, j = 0; i < s.length(); i++) {    // move left each outer
        for(; count != 0 && j < s.length(); j++) {   // run right inner
            if (hm[s.charAt(j)] > 0) {
                count--;
            }
            hm[s.charAt(j)]--;
        }
        if (count == 0) {
            result = (j - i) < result.length() ? s.substring(i, j) : result;
        }
        hm[s.charAt(i)]++;
        if (hm[s.charAt(i)] > 0) {
            count++;
        }
    }
    return result.length() == (s.length() + t.length()) ? "" : result;
}

private int[] parseToIntArray(String t) {
    int[] hm = new int[256];
    for (char c : t.toCharArray()) {
        hm[c]++;
    }
    return hm;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Sort

  • Always try to sort first before your algorithm.
    • number order, alphabetical order, linked list order, etc.
    • Easy for PRUNING
  • Two Sum
  • Search -> Binary Search
  • Permutation
  • Combination Sum
  • Merge Intervals
    • Given a collection of intervals, merge all overlapping intervals.
    • [1,3],[2,6],[8,10],[15,18] -> [1,6],[8,10],[15,18]

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Merge Intervals

Given a collection of intervals, merge all overlapping intervals.

Example Input: [1,3],[2,6],[8,10],[15,18]

Example Output: [1,6],[8,10],[15,18]

public List<Interval> merge(List<Interval> intervals) {
    if (intervals.size() == 0) {
        return new ArrayList<Interval>();
    }
    Collections.sort(intervals, new Comparator<Interval>(){
        @Override
        public int compare(Interval a1, Interval a2) {
            return a1.start - a2.start;		//neg, 0, pos
        } 
    });
    
    ArrayList<Interval> results = new ArrayList<Interval>();
    Interval pre = intervals.get(0);
    for (int i = 1; i < intervals.size(); i++) {
        if (intervals.get(i).start <= pre.end) {
            pre.end = Math.max(intervals.get(i).end, pre.end);
        } else {
            results.add(new Interval(pre.start, pre.end));
            pre = intervals.get(i);
        }
    }
    results.add(pre);    // Don't forget the last one
    return results;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

class Interval {
    int start;
    int end;
}

Linked List

  • Java variables & data types
    • Primitive Type & Reference Type
    • Variable Definition/Assignment, Parameter Passing
  • Definition
    • Linear collection, not continuous, same type
    • Accessing one node needs iterating all previous ones.
  • Basic Operation
    • Get, Add, Remove - O(n)
  • Dummy Node
    • Remove specialty for head node when structure change may happen. 
  • Two Pointers

function (ListNode node, int val) {

    node.val = 5; // original node changed.

    node = new ListNode(5); // no change.

    val = 6; // original val will never change.

}

Add: O(1) with tail node.

ListNode dummy = new ListNode(-1);

dummy.next = head

- kth node from the end.

- mid node of the list.

- Whether circle exists

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Linked List

  • Programming Tips
    • Try to simplify edge cases.
    • Keep one node's next before it is changed.
    • Check NULL when using while
      • while (cur != null) { cur.next } 
      • while (pre.next != null) { pre.next; pre.next.next; }
    • Test Cases
  • Make sure you think very clearly before writing code.
  • Practicing is the most important for Linked List

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Rotate List

Given a list, rotate the list to the right by k places, where k is non-negative

Example Input: 1->2->3->4->5, 2

Example Output: 4->5->1->2->3

public ListNode rotateRight(ListNode head, int n) {
    if (head == null || n == 0)
        return head;
    ListNode tail = head;
    int length = 1;
    while (tail.next != null) {
        tail = tail.next;
        length++;
    }  // Calculate length of the linked list.
    n %= length;
    if (n == 0) {
        return head;
    } // If it is going to do a full rotate, then no need to do.
    
    ListNode newHeadPre = head;
    int index = length - n - 1;
    while (index-- > 0) {
        newHeadPre = newHeadPre.next;
    } // Get the previous node of the new head.
    
    tail.next = head;
    head = newHeadPre.next;
    newHeadPre.next = null;
    return head;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head.

Example Input: 1->2->3->4

Example Output: 2->1->4->3

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

public ListNode swapPairs(ListNode head) {
    ListNode dummy = new ListNode(-1);
    dummy.next = head;
    ListNode pre = dummy;
    while (pre.next != null && pre.next.next != null) {
        ListNode first = pre.next, second = pre.next.next;
        first.next = second.next;
        second.next = first;
        pre.next = second;
        pre = first;
    }
    return dummy.next;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Stack & Queue

  • Definition
    • LIFO v.s. FIFO
  • Basic Operation
    • size, pop, push, peek
  • Implementation
    • Based on Array.
    • One pointer for Stack, two pointers for Queue.
  • When to use Stack & Queue
    • Stack: Deep First Search  - recursion.
    • Queue: Breadth First Search
  • Mono-increasing stack 

Array -> Queue

Array -> Stack

Stack <-> Queue

- Largest Rectangle in Histogram

- Trapping Rain Water

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Stack & Queue

  • Mono-increasing stack
    • Keep the elements in an "increasing" order so that previous elements can always extend to current one.
      • If new element is larger, push.
      • If new element is smaller, pop previous ones until the current one is the largest.

Copyright © 直通硅谷

http://www.zhitongguigu.com/

right: the end of the stack

left: the previous element

Balance Number

Given an array of ints.

Is there a number k in this array that k is larger than all the numbers before it and smaller than all the numbers after it?

[1,2,3,4,5] true

[6,2,3,8,10,9] true

[4,5,3,6] true

[4,3,5,2] false

[1] true

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Extra: return all balance numbers

Balance Number

Copyright © 直通硅谷

http://www.zhitongguigu.com/

public boolean existNumber(int[] nums) {
    Stack<Integer> stack = new Stack<>();
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > max) {
            stack.push(nums[i]);
            max = nums[i];
        } else {
            while (!stack.isEmpty() && nums[i] <= stack.peek()) {
                stack.pop();
            }
        }
    }
    return !stack.isEmpty();
}
  • <Key, Value> What to store as K and V
  • put(key, value)
  • get(key)
  • containsKey(key),
  • Set<Map.Entry<Key, Value>> entrySet(),
  • keySet()
  • putAll()

 

hashcode()

  • Collision

equals()

HashMap

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Copyright © 直通硅谷

http://www.zhitongguigu.com/

public int maxPoints(Point[] points) {
    if (points == null || points.length == 0) {
        return 0;
    }
    int res = 0, n = points.length;
    Map<Pair, Integer> hm = new HashMap<>();
    for (int i = 0; i < n; i++) {
        hm.clear();
        int samePoint = 0, localMax = 0;
        for (int j = i + 1; j < n; j++) {
            int x = points[i].x - points[j].x;
            int y = points[i].y - points[j].y;
            if (x == 0 && y == 0) {
                samePoint++;
                continue;
            }
            int gcd = GCD(x, y);
            Pair p = new Pair(x/gcd, y/gcd);    // why?
            if (!hm.containsKey(p)) {
                hm.put(p, 1);
            } else {
                hm.put(p, hm.get(p) + 1);
            }
            localMax = Math.max(localMax, hm.get(p));
        }
        res = Math.max(res, localMax + samePoint + 1);
    }
    return res;
}

Max Points on a Line

Given n points on a 2D plane

 find the maximum number of points that lie on the same straight line.

Cartesian coordinate system

笛卡尔坐标系(直角坐标系)

Copyright © 直通硅谷

http://www.zhitongguigu.com/

class Pair {
    int x, y;
    public Pair(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int hashCode() {
        String s = x + "," + y;
        return s.hashCode();
    }
    public boolean equals(Object p) {
        if (this == p) {
            return true;
        }
        if (p == null || this.getClass() != p.getClass()) {
            return false;
        }
        Pair pair = (Pair) p;
        return this.x == pair.x && this.y == pair.y;
    }
}

private int GCD(int x, int y) {
    if (y == 0) {
        return x;
    }
    return GCD(y, x%y);
}

Max Points on a Line

Given n points on a 2D plane

 find the maximum number of points that lie on the same straight line.

Copyright © 直通硅谷

http://www.zhitongguigu.com/

// Greatest Common Divisor
public int GCD(int a, int b) {
    if (a == 0 || b == 0) {
        return a == 0 ? b : a;
    }
    if (a == b) {
        return a;
    }
    if (a > b) {
        return GCD(a - b, b);
    } else {
        return GCD(a, b - a);
    }
}

// modified version
// work if x and y are both positive
// return negative if y is negative.
// Normal mathematical GCD always return positive.
private int GCD(int x, int y) {
    if (y == 0) {
        return x;
    }
    return GCD(y, x % y);
}

// Least Common Multiple  
public int LCM(int a, int b) {
    return a * b / GCD(a, b);
}

Max Points on a Line

Greatest Common Divisor

GCD 最大公约数

 

Least Common Multiple

LCM 最小公倍数

Euclidean algorithm

欧几里得算法

辗转相除

Binary Search

  • The fastest way to search in sorted array. O(logN)
  • Be careful with INFINITE LOOP.
    • int begin = 0, end = nums.length; [begin, end)
    • int begin = 0, end = nums.length-1; [begin, end]
    • Condition to terminate the loop
    • Condition for edge cases
    • In each loop iteration, there can be only two cases.
      • The range of [begin, end]/[begin, end) decrease.
      • Jump out of the loop
  • Make sure all cases are taken care of before writing code.
  • Insert Position
    • Search 2D Matrix.

Find Minimum in Rotate Sorted Array

 

 

 

- Comparing mid with begin/end is different.

Copyright © 直通硅谷

http://www.zhitongguigu.com/

public boolean searchMatrix(int[][] matrix, int target) {
    int begin = 0, end = matrix.length, mid = 0;
    while (begin < end) {
        mid = (begin + end) >> 1;
        if (matrix[mid][0] == target) {
            return true; 
        } else if (matrix[mid][0] > target) {
            end = mid ;
        } else {
            begin = mid + 1;
        }
    }
    int row = begin - 1;
    if (row < 0) return false;
    begin = 0;
    end = matrix[0].length;
    while (begin < end) {
        mid = (begin + end) >> 1;
        if (matrix[row][mid] == target) {
            return true; 
        } else if (matrix[row][mid] > target) {
            end = mid;
        } else {
            begin = mid + 1;
        }
    }
    return false;
}

Search a 2D Matrix

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

- Integers in each row are sorted from left to right.

- The first integer of each row is greater than the last integer of the previous row.

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Recursion

  • Divide problems into smaller instances, solve smaller problems and then solve original problem
  • Principles
    • How to represent the question
      • Parameters that define the question
      • Parameters that store the temporary result or state
    • Base case
    • Recursion rules
      • Backtracking
      • Pruning strategy
  • Recursion is very similar to real thinking.
    • Pseudo code can help a lot with these questions. 

- Pruning before going into next recursion iteration is very important.

- Permutation II

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Permutation II

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:

[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

Permutation II

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> result = new ArrayList<>();
    Arrays.sort(nums);
    dfs(result, intToObj(nums), 0);
    return result;
}
private void dfs(List<List<Integer>> result, Integer[] nums, int index) {
    // we don't have to wap the last number with itself.
    if (index == nums.length - 1) {
        result.add(new LinkedList<Integer>(Arrays.asList(nums)));
        return;
    }
    for (int i = index; i < nums.length; i++) {
        if (!(i > index && (nums[i] == nums[index]))) { 
            // (i == index || nums[i] != nums[index])
            swap(nums, index, i);
            dfs(result, Arrays.copyOf(nums, nums.length), index + 1);
            // why not swap back?
        }
    }
}
private void swap(Integer[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}
private Integer[] intToObj(int[] nums) {
    Integer[] result = new Integer[nums.length];
    for (int i = 0; i < nums.length; i++) {
        result[i] = nums[i];
    }
    return result;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

古之欲明明德于天下者,先治其国;欲治其国者,先齐其家;欲齐其家者,先修其身;欲修其身者,先正其心;欲正其心者,先诚其意;欲诚其意者,先致其知,致知在格物。

物格而后知至,知至而后意诚,意诚而后心正,心正而后身修,身修而后家齐,家齐而后国治,国治而后天下平。

Recursion

Copyright © 直通硅谷

http://www.zhitongguigu.com/

[GoValley-201612] Midterm Review

By govalley201612

[GoValley-201612] Midterm Review

  • 787