Daily Archives: September 2, 2016

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.