Monthly Archives: October 2015

possible sum of a number

Given a number n, find all sub sets:
For example given 4, should return [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]]

My Solution:

public static List<List<Integer>> permutateNumber(int n) {
    List<List<Integer>> result = new ArrayList<List<Integer>>();
    List<Integer> currResult = new ArrayList<Integer>();
    permutateNumberUtil(result, currResult, n, 1);
    return result;
}

public static void permutateNumberUtil(List<List<Integer>> result, List<Integer> currResult, int n, int currNum) {
    if(n<=0) {
        List<Integer> list = new ArrayList<Integer>(currResult);
        result.add(list);
        return;
    }
    for(int i=currNum; i<=n; i++) {
        currResult.add(i);
        permutateNumberUtil(result, currResult, n-i, i);
        currResult.remove(currResult.size()-1);
    }
}

Wild card match

This post responds to junmin’s code: link

Below is my recursion implementation for ‘?’ and ‘*’ regular expression match:

public static boolean matchReg(String str, String reg) {
    return matchRegUtil(str, 0, reg, 0);
}

public static boolean matchRegUtil(String str, int strPos, String reg, int regPos) {
    if(strPos>=str.length() && regPos>=reg.length()) {
        return true;
    }
    else if(regPos>=reg.length()) {
        return false;
    }
    else if(strPos>=str.length()) {
        for(int i=regPos; iif(reg.charAt(i)!='*') {
                return false;
            }
        }
        return true;
    }
    if(reg.charAt(regPos)==str.charAt(strPos)||reg.charAt(regPos)=='?') {
        return matchRegUtil(str, strPos+1, reg, regPos+1);
    }
    else if(reg.charAt(regPos)=='*'){
        for(int i=strPos-1; iif(matchRegUtil(str, i+1, reg, regPos+1)) {
                return true;
            }
        }
    }
    return false;
}

Permutation, Subset, All group of Palindrome

Today, I found a great coding style for series problem, like permutation, subset and group of palindrome:

public static void getPermutationUtil(String str, int start, List<List<String>> result, List<String> currResult) {
    if(start==str.length()) {
        ArrayList<String> curr = new ArrayList<String>(currResult);
        result.add(curr);
    }
    else {
        for(int i=start; i<str.length(); i++) {
            String currStr = str.substring(start, i+1);
            currResult.add(currStr);
            getPermutationUtil(str, i + 1, result, currResult);
            currResult.remove(currResult.size()-1);
        }
    }
}

When we construct a subset of an array, we try to build it on arr[start,…,length-1]. The arr[0,…,i-1] is already done and saved in currResult. When start equals length, it means it ends and we save this currResult in result. Below are the 3 types of application of this coding style:
Permutation

public static List<List<String>> getPermutation(String str) {
    List<List<String>> result = new ArrayList<List<String>>();
    getPermutationUtil(str, 0, result, new ArrayList<String>());
    return result;
}

public static void getPermutationUtil(String str, int start, List<List<String>> result, List<String> currResult) {
    if(start==str.length()) {
        ArrayList<String> curr = new ArrayList<String>(currResult);
        result.add(curr);
    }
    else {
        for(int i=start; i<str.length(); i++) {
            String currStr = str.substring(start, i+1);
            currResult.add(currStr);
            getPermutationUtil(str, i + 1, result, currResult);
            currResult.remove(currResult.size()-1);
        }
    }
}

SuperSet, This is the same problem from here, which is a another solution.

public static List<List<Character>> getSuperSet(char[] chs) {
    List<List<Character>> result = new ArrayList<List<Character>>();
    getSuperSetUtil(chs, 0, result, new ArrayList<Character>());
    return result;
}

public static void getSuperSetUtil(char[] chs, int start, List<List<Character>> result, List<Character> currResult) {
    if(start==chs.length) {
        ArrayList<Character> curr = new ArrayList<Character>(currResult);
        result.add(curr);
    }
    else {
        //count current char
        currResult.add(chs[start]);
        getSuperSetUtil(chs, start + 1, result, currResult);
        currResult.remove(currResult.size()-1);
        //doesn't count current char
        getSuperSetUtil(chs, start+1, result, currResult);
    }
}

public static void printSuperSet(char[] chs) {
    List<List<Character>> sets = new ArrayList<List<Character>>();
    int size = (int)Math.pow(2, chs.length);
    for(int i=0; i<size; i++) {
        List<Character> list = new ArrayList<Character>();
        for(int j=0; j<chs.length; j++) {
            if(((1<<j)&i)>0) {
                list.add(chs[j]);
            }
        }
        sets.add(list);
    }
    System.out.println(sets);
}

All Palindrome Partition

public static List<List<String>> getAllPalindromePartition(String str) {
    List<List<String>> result = new ArrayList<List<String>>();
    getAllPalindromePartitionUtil(str, 0, result, new ArrayList<String>());
    return result;
}

public static void getAllPalindromePartitionUtil(String str, int start, List<List<String>> result, List<String> currResult) {
    if(start==str.length()) {
        ArrayList<String> curr = new ArrayList<String>(currResult);
        result.add(curr);
    }
    else {
        for(int i=start; i<str.length(); i++) {
            String currStr = str.substring(start, i+1);
            if(isPalindrome(currStr)) {
                currResult.add(currStr);
                getAllPalindromePartitionUtil(str, i + 1, result, currResult);
                currResult.remove(currResult.size()-1);
            }
        }
    }
}

public static boolean isPalindrome(String str) {
    int left=0, right=str.length()-1;
    while(left<right) {
        if(str.charAt(left)==str.charAt(right)) {
            left++;
            right--;
        }
        else {
            return false;
        }
    }
    return true;
}

Check my code on github:Permutation, Subset, All palindrome sets

Minimum palindrome partition

One traditional question is to find the longest palindrome in a string. This has 3 ways to solve:
1. For each element, use 2 pointers to move to left and right. And find the furthest it can move.
2. Use lcs to find the longest common substring between string and reversed-string. Take “abccbd” as example, we find LCS of “abccbd and “dbccba”.
3. Use dynamic programming, this way is similar to junmin’s post to find the longest parenthesis. link

There is another quesiton which can be developed. It is find the minimum number that we partition the string to all palindrome string. We can similar way to above method 3 to solve this problem.

We use array. arr[i][j] is the minimum palindrom partition number. For element where i=j, we set arr[i][j]=1. For example if we want to calculate arr[3][6]. If arr[2][5] is 1, and str[3]==str[6], then we know str[3]…str[6] is a palindrome. Or arr[3][6] = min {arr[3][3]+arr[4][6], arr[3][4]+arr[5][6], arr[3][5]+arr[6][6]}

After we built this array, arr[0][length-1] will be the answer.

check my code on github: link

super set by bit array

This is my try for super set problem given by junmin link.
Given a set of unique characters, generate its superset. example: a, b, c, its superset are:
[[], [c], [b], [c, b], [a], [c, a], [b, a], [c, b, a]]

Normal way is to use recursion. But another way is to use bit array. For {a, b, c}, 001 represents {c}, 110 represents {a, b}. In this way, all we need is to iterate a number from 000 to 111 to get all sets.

/**
 * Created by lipeng on 2015/5/15.
 */
public class SuperSet {
    public static void main(String[] args) {
        char[] chs = {'a', 'b', 'c', 'd'};
        printSuperSet(chs);
    }

    public static void printSuperSet(char[] chs) {
        List<List<Character>> sets = new ArrayList<List<Character>>();
        int size = (int)Math.pow(2, chs.length);
        for(int i=0; i<size; i++) {
            List<Character> list = new ArrayList<Character>();
            for(int j=0; j<chs.length; j++) {
                if(((1<<j)&i)>0) {
                    list.add(chs[j]);
                }
            }
            sets.add(list);
        }
        System.out.println(sets);
    }

}

Best Time to Buy and Sell Stock III

This is from leetcode: link. Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions.

The solution is to maintain 2 array, maxLeft[], maxRight[]. maxLeft[i] maintains the max profit from price[0],…,price[i] by one transaction. maxRight[i] maintains from price[i],…,price[length-1] by one transaction. Then we find i where we can get max{maxLeft[i]+maxRight[i]}.

Check my code on github: link

Buy stock to get max profit with at most K times

This is from leetcode, Best Time to Buy and Sell Stock IV. Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most k transactions.

The answer is to use dynamic programming by local and global 2-dimension array to implement dynamic programming:
local[i][j] = max{local[i-1][j]+diff, global[i-1][j-1]+max(diff,0)}
global[i][j] = max{local[i][j], global[i-1][j]}

local[i][j] means we do at most jth transaction at i price. If we already got the max profit at most jth transaction at i-1 price, for local[i][j], we just add price[i]-price[i-1], no matter if it is negative or positive. Another option for local[i][j] is that we get it from global[i-1][j-1]+max(diff,0). If diff is less than 0, we then ignore the transaction price[i]-price[i-1]

global[i][j] could be got from local[i][j] or global[i-1][j], which is easy to understand.

Check my code on github: link

Get max histogram rectangle

I solved this problem one year ago. This time I solved it again and wrote some analysis for it.

Problem definition:
Find the largest rectangular area possible in a given histogram where the largest rectangle can be made of a number of contiguous bars. For simplicity, assume that all bars have same width and the width is 1 unit.

For example, consider the following histogram with 6 bars of heights {6, 2, 5, 4, 5, 6}. The largest possible rectangle possible is 12 (see the below figure, the max area rectangle is highlighted in red)
histogram1

I think this problem has some application background. That is for each number in set of numbers, find farthest continuous left and right of numbers which all larger than the number. For example, for element 3, the right most it can reach is 4, the left most it can reach is element 2.

To solve this problme, stach is used. We should firstly iterate number from left to right by stack by below rules:
1.From left to right
2.If current is smaller than stack top, then pop stack. After pop stack tp, calculate area size for position tp
3.In the end, push current index

Then we pop all element in stack:
1. For each poped element, use arrary.length and stack.peek() to calculate area size.

The process is like below:
From left to right
historgram2

Pop the rest stack
histogram3

github: link

Longest valid parentheses

Given a string containing just the characters ‘(‘ and ‘)’, find the length of the longest valid (well-formed) parentheses substring

For “(()”, the longest valid parentheses substring is “()”, which has length = 2.
Another example is “)()())”, where the longest valid parentheses substring is “()()”, which has length = 4.

Below are the 2 ways how I implemented it.
For getMaxParentheses2(), it always stores element into stack. When there is a pop function, it will calculate the size by curr_pos and peek() for the length.
For getMaxParentheses(), it only stores legal parentheses in stack. In this way, it uses start variable to store the legal parentheses start position. When there is a pop function and stack is empty, it will use curr_pos-start to get the length, or it will still use curr_pos and peek() for the length.

public static int getLongestParentheses(char[] chs) {
    if(chs==null||chs.length==0) {
        return 0;
    }
    int maxSize = 0;
    int start = 0;
    Stack stack = new Stack();
    for(int i=0; ilength; i++) {
        if(chs[i]=='(') {
            stack.push(i);
        }
        else if(stack.empty()) {
            start = i + 1;
        }
        else {
            stack.pop();
            maxSize = stack.isEmpty() ? Math.max(maxSize, i-start+1) : Math.max(maxSize, i-stack.peek());
        }
    }
    return maxSize;
}

public static int getMaxParentheses2(char[] chs) {
    Stack stack = new Stack();
    int max = Integer.MIN_VALUE;
    for(int i=0; ilength; i++) {
        if(stack.isEmpty() || chs[i]=='(' || chs[stack.peek()]==')') {
            stack.push(i);
        }
        else {
            stack.pop();
            int currMax = stack.isEmpty() ? i+1 : i-stack.peek();
            max = currMax > max ? currMax : max;
        }
    }
    return max;
}

Check my code on github: link
Besides, this problem also can be solved by dp. Here is from junmin’s solution: link

The Maximum Volume of Trapped Rain Water

Problem description:
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
For example, Given the input
[0,1,0,2,1,0,1,3,2,1,2,1]

the return value would be
6

This problem can be solved in O(n) time, by going through from left to right, and right to left to record the maximum height to now in O(n) time, O(n) space. The code is like below:

public int trap2(int[] height) {
    int[] leftDp = new int[height.length], rightDp = new int[height.length];
    int leftMax = 0, rightMax = 0;
    for (int i = 0; i < height.length; i++) {
        leftDp[i] = leftMax;
        leftMax = Math.max(leftMax, height[i]);
        rightDp[height.length - i - 1] = rightMax;
        rightMax = Math.max(rightMax, height[height.length - i - 1]);
    }
    int ans = 0;
    for (int i = 0; i < height.length; i++) {
        int hi = Math.min(leftDp[i], rightDp[i]);
        ans += hi <= height[i] ? 0 : (hi - height[i]);
    }
    return ans;
}

 

However, this problem can be solved in O(n) time and O(1) space. Starting from left and right. Handle the smaller one and update the area size:

public int trap(int[] height) {
    int leftMax = 0, rightMax = 0, areaSize= 0, left = 0, right = height.length - 1;
    while (left <= right) {
        if (height[left] <= height[right]) {
            leftMax = Math.max(leftMax, height[left]);
            areaSize += leftMax - height[left++];
        }
        else {
            rightMax = Math.max(rightMax, height[right]);
            areaSize += rightMax - height[right--];
        }
    }
    return areaSize;
}

Check my code on github: link