Monthly Archives: September 2016

Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

For example:
Given array A = [2,3,1,1,4]

The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)

Solution. At first sight, this problem looks like coin change, which has O(n^2) solution. But this exceeds time limit. Then I found this problem can be solved in BFS way. Basically, we can think all elements which we can reach at most 1 step as level 1, all elements which we can reach at most 2 steps as level 2. In level 1, we find the furthest element level 1 can reach, the furthest will be the boundary for level 2.

jumpgameii

Below is an example for the jump.

jumpgameii3

elements in level 1 can mostly jump to position 4. In level 2, it can mostly jump to position 8.

public static int jump(int[] A) {
    int currLong = 0, nextLong = 0, level = 0;
    for (int i = 0; i < A.length; i++) {
        if (i - 1 == currLong) {
            level++;
            currLong = nextLong;
        }
        nextLong = Math.max(nextLong, A[i] + i);
    }
    return level;
}

Check my code on github.

First Missing Number

leetcode 41.

Given an unsorted integer array, find the first missing positive integer.

For example,
Given [1,2,0] return 3,
and [3,4,-1,1] return 2.

Your algorithm should run in O(n) time and uses constant space.

Solution. I learned the solution from here. The idea is try as much as possible to rearrange array like [1, 2, 3, 4, 5, …].

There are some cases when we pass the iteration.

A[i] < 1 || A[i] > A.length, invalid. For example, we can put [1, 2, 3, 4, 5]. It shows at least we can put 1, at most, we can put 5.

A[i] == i + 1. This is valid situation, so pass.

A[A[i] – 1] == A[i]. Value of position A[i] – 1 is the same as value of A[i], so we don’t swap. One of case is [1, 1].

In all the code is like:

public int firstMissingPositive(int[] A) {
    int i = 0;
    while (i < A.length) {
        // A[i] < 1, A[i] > len, eliminate the invalid value.
        // A[i] == i + 1 is valid, so pass
        // A[i] - 1 and i position has same value. This is the case [1, 1]
        if (A[i] < 1 || A[i] > A.length || A[i] - 1 == i || A[A[i] - 1] == A[i]) {
            i++;
        }
        else {
            swap(A, A[i] - 1, i);
        }
    }
    for (i = 0; i < A.length && A[i] == i + 1; i++);
    return i + 1;
}

private void swap(int[] A, int i, int j){
    int temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

Check my code on github.

Sudoku

I came across the sudoku problem in leetcode 37. Here I wrote a page javascript version to solve this problem.

Check my code on github.

Arrays.asList(), Array to List

This is a summary for Arrays.asList() and transformation from Array to List. See below examples and comments.

public static void test1() {
    boolean[] b = new boolean[10];

    // wrong, Arrays.asList doesn't accept array of primitive type
    List<Boolean> list = Arrays.asList(b);
}

public static void test2() {
    Boolean[] b = new Boolean[10];

    // correct, because it is not primitive type
    List<Boolean> list1 = Arrays.asList(b);

    // correct, a second way for creating List for Arrays.asList()
    List<Boolean> list2 = Arrays.asList(true, true, true);
}

public static void test3() {
    Boolean[] b = new Boolean[10];
    List<Boolean> list = Arrays.asList(b);

    // exception, Arrays.asList doesn't support add element.
    list.add(true);
}

public static void test4() {
    Boolean[] b1 = new Boolean[10];
    List<Boolean> list = new ArrayList<>(Arrays.asList(b1));

    // correct, because it is a normal List
    list.add(true);
}

Check my code on github.

Bulls and Cows

leetcode 299.

You are playing the following Bulls and Cows game with your friend: You write down a number and ask your friend to guess what the number is. Each time your friend makes a guess, you provide a hint that indicates how many digits in said guess match your secret number exactly in both digit and position (called “bulls”) and how many digits match the secret number but locate in the wrong position (called “cows”). Your friend will use successive guesses and hints to eventually derive the secret number.

For example:

Secret number:  "1807"
Friend's guess: "7810"

Hint: 1 bull and 3 cows. (The bull is 8, the cows are 0, 1 and 7.)

Write a function to return a hint according to the secret number and friend’s guess, use A to indicate the bulls and B to indicate the cows. In the above example, your function should return "1A3B".

Please note that both secret number and friend’s guess may contain duplicate digits, for example:

Secret number:  "1123"
Friend's guess: "0111"

In this case, the 1st 1 in friend’s guess is a bull, the 2nd or 3rd 1 is a cow, and your function should return "1A1B".

You may assume that the secret number and your friend’s guess only contain digits, and their lengths are always equal.

Solution. This problem is similar to Isomorphic. An awesome solution is from here. We maintain a int[] array with size 10. Whenever we see a secret, we make the secret digit in array decrease. Whenever we see a guess, we make the guess digit in array increase.

// secret makes num--, guess makes num++
public static String getHint(String secret, String guess) {
    int bull = 0, cow = 0;
    int[] num = new int[10];
    for (int i = 0; i < secret.length(); i++) {
        if (secret.charAt(i) == guess.charAt(i)) {
            bull++;
            continue;
        }
        if (num[secret.charAt(i) - '0']-- > 0) {
            cow++;
        }
        if (num[guess.charAt(i) - '0']++ < 0) {
            cow++;
        }
    }
    return bull + "A" + cow + "B";
}

Check my code on github.

Metric for bloom filter

Assume totally has 1M record. We want test is 1% wrong rate. 7 hash functions. In this way, it totally need around 1.14MB bits for the bloom filter.

Bloom filter block those which doesn’t exist. For those bloom filter think the value exist, there is 1% chance wrong.

Refer bloom filter calculator. http://hur.st/bloomfilter?n=1000000&p=0.01

strStr

leetcode 28.

Implement strStr().

Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

Solution. This problem is asking to implement source.indexOf(target) method. A brilliant solution is from here.

public int strStr(String source, String target) {
    for (int i = 0; true; i++) {
        for (int j = 0; true; j++) {
            if (j == target.length()) {
                return i;
            }
            if (i + j == source.length()) {
                return -1;
            }
            if (source.charAt(i + j) != target.charAt(j)) {
                break;
            }
        }
    }
}

Another effective solution is KMP:

public static int[] getNext(String str) {
    int[] next = new int[str.length()];
    int i = 0, j = 1;
    while (j < str.length() - 1) {
        if (str.charAt(i) == str.charAt(j)) {
            i++;
            j++;
            next[j] = i;
        }
        else if (i != 0) {
            i = 0;
        }
        else {
            j++;
        }
    }
    return next;
}

public static int strStr(String src, String pattern) {
    int[] next = getNext(pattern);
    int i = 0, j = 0;
    while (i < src.length() && j < pattern.length()) {
        if (src.charAt(i) == pattern.charAt(j)) {
            i++;
            j++;
        }
        else if (j != 0) {
            j = next[j];
        }
        else {
            i++;
        }
    }
    return j == pattern.length() ? i - pattern.length() : -1;
}

 

Check my code on github.

Isomorphic Strings

leetcode 205.

Given two strings s and t, determine if they are isomorphic.

Two strings are isomorphic if the characters in s can be replaced to get t.

All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.

For example,
Given "egg", "add", return true.

Given "foo", "bar", return false.

Given "paper", "title", return true.

Solution. A great solution is from here. It records the position of each char. If position of char are not the same, return false. Each loop will update the position of the char.

public boolean isIsomorphic(String s, String t) {
    int[] pos = new int[512];
    for (int i = 0; i < s.length(); i++) {
        if (pos[s.charAt(i)] != pos[t.charAt(i) + 256]) {
            return false;
        }
        pos[s.charAt(i)] = pos[t.charAt(i)] = i + 1;
    }
    return true;
}

Check my code on github.

Reverse Nodes in k-Group

leetcode 25.

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For example,
Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

Solution. Should pay attention if we do 1->2->3->4->5->6->7->8->9->10, k = 4. Then the result should be: 4->3->2->1->8->7->6->5->9->10. We don’t swap the 3rd group, which is last 2 elements.

So the idea is that we swap each k elements group. This is a general process described in this Reverse Linked List II problem. A front node should be in the front to monitor if current group is reversible.

In below example, it reverse each k elements group. When front is null, we stop reversing current group.

reversekgroup2

public static ListNode reverseKGroup(ListNode head, int k) {
    ListNode dummy = new ListNode(0), front = head;
    dummy.next = head;
    head = dummy;
    for (int i = 1; i < k && front != null; i++) {
        front = front.next;
    }
    while (front != null) {
        ListNode tail = head.next, curr = tail.next;
        for (int i = 1; i < k; i++) {
            front = front == null ? null : front.next;
            tail.next = curr.next;
            curr.next = head.next;
            head.next = curr;
            curr = tail.next;
        }
        front = front == null ? null : front.next;
        head = tail;
    }
    return dummy.next;
}

Check my code on github.

4Sum

leetcode 18.

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

Solution. 3 Sum outer loop uses i, inner loop uses lo, hi. For 4 Sum, we need to use outer loop i, j. When i, j are fixed, we loop inner lo, hi.

In order to avoid the duplicate result, every time when we move i, j, lo, hi, we need to move them until to a different element.

public static List<List<Integer>> fourSum(int[] nums, int target) {
    List<List<Integer>> ans = new ArrayList<>();
    Arrays.sort(nums);
    int i = 0;
    while (i < nums.length - 3) {
        int j = i + 1;
        while (j < nums.length - 2) {
            int lo = j + 1, hi = nums.length - 1;
            while (lo < hi) {
                int sum = nums[i] + nums[j] + nums[lo] + nums[hi];
                if (sum == target) {
                    ans.add(Arrays.asList(nums[i], nums[j], nums[lo], nums[hi]));
                    while (++lo < hi && nums[lo] == nums[lo - 1]);  // one line technique to move lo until a different element.
                    while (lo < --hi && nums[hi] == nums[hi + 1]);
                }
                else if (sum > target) {
                    hi--;
                }
                else {
                    lo++;
                }
            }
            while (++j < nums.length - 2 && nums[j] == nums[j - 1]);
        }
        while (++i < nums.length - 3 && nums[i] == nums[i - 1]);
    }
    return ans;
}

Check my code on github.