Thursday, January 28, 2016

LeetCode [330] Patching Array

Ref
[1] https://leetcode.com/problems/patching-array/
[2] https://leetcode.com/discuss/82822/solution-explanation

Wednesday, January 20, 2016

LeetCode [329] Longest Increasing Path in a Matrix

329. Longest Increasing Path in a Matrix
Hard
Given an integer matrix, find the length of the longest increasing path.
From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).
Example 1:
Input: nums = 
[
  [9,9,4],
  [6,6,8],
  [2,1,1]
] 
Output: 4 
Explanation: The longest increasing path is [1, 2, 6, 9].
Example 2:
Input: nums = 
[
  [3,4,5],
  [3,2,6],
  [2,2,1]
] 
Output: 4 
Explanation: The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
    vector<vector<int>> dir{{1,0},{-1,0},{0,-1},{0,1}};
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        int m = matrix.size();
        if(m==0) return 0;
        int n = matrix[0].size();
        if(n==0) return 0;
        
        vector<vector<int>> dp(m, vector<int>(n, -1));
        int ret = 0;
        for(int i=0; i<m; ++i){
            for(int j=0; j<n; ++j){
                if(dp[i][j]<0){
                    dfs(matrix, dp, i, j, m, n);
                }
                ret = max(ret, dp[i][j]);
            }
        }
        return ret;
    }
    
    void dfs(vector<vector<int>>& matrix, vector<vector<int>>& dp, int i, int j, int m, int n){
        dp[i][j] = 1;
        for(auto d:dir){
            int ii = i+d[0], jj = j+d[1];
            if(ii>=0 && ii<m && jj>=0 && jj<n && matrix[i][j]<matrix[ii][jj]){
                if(dp[ii][jj]<0){
                    dfs(matrix, dp, ii, jj, m, n);
                }
                dp[i][j] = max(dp[i][j], 1+dp[ii][jj]);
            }
        }
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//Java
class Solution {
    int[][] dir = new int[][]{{0,1},{1,0},{0,-1},{-1,0}};
    int ret = 0;
    int m, n;
    int[][] dp;
    public int longestIncreasingPath(int[][] matrix) {
        m = matrix.length;
        if(m==0) return 0;
        n = matrix[0].length;
        if(n==0) return 0;
        
        dp = new int[m][n];
        for(int i=0; i<m; ++i){
            for(int j=0; j<n; ++j){
                dp[i][j] = -1;
            }
        }

        for(int i=0; i<m; ++i){
            for(int j=0; j<n; ++j){
                if(dp[i][j]<0) helper(matrix, i, j);
                ret = Math.max(ret, dp[i][j]);
            }
        }
        
        return ret;
    }

    void helper(int[][] matrix, int i, int j){
        dp[i][j] = 1;
        for(int[] d : dir){
            int ii = i + d[0];
            int jj = j + d[1];
            if(ii>=0 && ii<m && jj>=0 && jj<n && matrix[i][j]<matrix[ii][jj]){
                if(dp[ii][jj]<0){
                    helper(matrix, ii, jj);
                }
                dp[i][j] = Math.max(dp[i][j], dp[ii][jj]+1);
            }
        }
    }
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//O((mn)^2)
class Solution {
    int m, n;
    int[][] dirs = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
    public int longestIncreasingPath(int[][] matrix) {
        m = matrix.length;
        if(m == 0) return 0;
        n = matrix[0].length;
        if(n == 0) return 0;

        int[][] dp = new int[m][n];
        for(int i=0; i<m; ++i){
            Arrays.fill(dp[i], 1);
        }

        boolean cont = true;
        while(cont){
            cont = false;
            for(int i=0; i<m; ++i){
                for(int j=0; j<n; ++j){
                    for(int[] d : dirs){
                        int ii = i+d[0], jj = j+d[1];
                        if(ii>=0 && ii<m && jj>=0 && jj<n){
                            if(matrix[ii][jj]>matrix[i][j]){
                                if(dp[ii][jj]<dp[i][j]+1){
                                    cont = true;
                                    dp[ii][jj] = dp[i][j]+1;
                                }
                            }
                        }
                    }
                }
            }
        }

        int ret = 0;
        for(int i=0; i<m; ++i){
            for(int j=0; j<n; ++j){
                ret = Math.max(ret, dp[i][j]);
            }
        }

        return ret;
    }
}

Saturday, January 16, 2016

LeetCode [328] Odd Even Linked List

 328. Odd Even Linked List

Medium

Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.

You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.

Example 1:

Input: 1->2->3->4->5->NULL
Output: 1->3->5->2->4->NULL

Example 2:

Input: 2->1->3->5->6->4->7->NULL
Output: 2->3->6->7->1->5->4->NULL

 

Constraints:

  • The relative order inside both the even and odd groups should remain as it was in the input.
  • The first node is considered odd, the second node even and so on ...
  • The length of the linked list is between [0, 10^4].
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if(!head) return NULL;
        ListNode* p = head->next;
        ListNode* t = head;
        while(p && p->next){
            ListNode* next = p->next->next;
            ListNode* c = p->next;
            c->next = t->next;
            t->next = c;
            t = c;
            p->next = next;
            p = next;
        }
        return head;
    }
};

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode oddEvenList(ListNode head) {
        ListNode HO = new ListNode();
        ListNode HE = new ListNode();
        ListNode pO = HO;
        ListNode pE = HE;
        ListNode p = head;
        int i=1;
        while(p!=null){
            ListNode next = p.next;
            p.next = null;
            if(i%2==1){
                pO.next = p;
                pO = p;
            }else{
                pE.next = p;
                pE = p;
            }
            p = next;
            i++;
        }
        pO.next = HE.next;
        return HO.next;
    }
}

Monday, January 11, 2016

LeetCode [327] Count of Range Sum

327. Count of Range Sum
Hard

Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.
Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.

Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.

Example:

Input: nums = [-2,5,-1], lower = -2, upper = 2,
Output: 3 
Explanation: The three ranges are : [0,0], [2,2], [0,2] and their respective sums are: -2, -1, 2.

 

Constraints:

  • 0 <= nums.length <= 10^4
//C++
//C++: TLE Divide and Conquer
class Solution {
public:
    int countRangeSum(vector<int>& nums, int lower, int upper) {
        if(nums.empty() || lower>upper) return 0;
        int n = nums.size();
        if(n==1) return nums[0]>=lower&&nums[0]<=upper?1:0;
        vector<int> left(nums.begin(), nums.begin()+n/2);
        vector<int> right(nums.begin()+n/2, nums.end());
        int nl = countRangeSum(left, lower, upper);
        int nr = countRangeSum(right, lower, upper);

        for(int i=left.size()-2; i>=0; --i){
            left[i] += left[i+1];
        }
        for(int i=1; i<right.size(); ++i){
            right[i] += right[i-1];
        }
        sort(right.begin(), right.end());

        int c = 0;
        for(auto e:left){
            int a = lower-e, b = upper-e;
            int l = 0, r = right.size()-1;
            while(l<=r){
                if(right[l]<a){
                    l++;
                }else if(right[r]>b){
                    r--;
                }else{
                    break;
                }
            }
            c += r-l+1;
        }
        return c+nl+nr;
    }
};
]]></script>

<script class="brush: js" type="syntaxhighlighter"><![CDATA[
//C++: 72ms
typedef long long ll;

class Solution {
public:
    vector<ll> dm(vector<ll> nums, int lower, int upper, int &ret){
        int n = nums.size();
        if(n<2) return nums;
        vector<ll> left = dm(vector<ll>(nums.begin(), nums.begin()+n/2), lower, upper, ret);
        vector<ll> right = dm(vector<ll>(nums.begin()+n/2, nums.end()), lower, upper, ret);
        int nl = left.size(), nr = right.size(), t = 0, i = 0, j = 0, k = 0, index=-1;
        vector<ll> merge(n);
        for(; i<nl; ++i){
            while(j<nr && right[j]-left[i]<lower) j++;
            while(k<nr && right[k]-left[i]<=upper) k++;
            ret += k-j;
            while(t<nr && right[t]<=left[i]){
                merge[++index] = right[t++];
            }
            merge[++index] = left[i];
        }
        while(index<n-1){
            merge[++index] = right[t++];
        }
        return merge;
    }


    int countRangeSum(vector<int>& nums, int lower, int upper) {
        int ret = 0, n =  nums.size()+1;
        vector<ll> sums(n, 0);
        for(int i=1; i<n; ++i) sums[i] = sums[i-1] + nums[i-1];
        dm(sums, lower, upper, ret);
        return ret;
    }
};
//Java
class Solution {
    public int countRangeSum(int[] nums, int lower, int upper) {
        int n = nums.length;
        long[] array = new long[n+1];
        for(int i=1; i<=n; ++i){
            array[i] = array[i-1] + nums[i-1];
        }
        return helper(array, 0, n, lower, upper);
    }

    int helper(long[] array, int start, int end, int lower, int upper){
        if(end-start+1<2) return 0;
        int mid = (start+end)/2, count = 0;
        count += helper(array, start, mid, lower, upper);
        count += helper(array, mid+1, end, lower, upper);

        int j = mid+1, k = mid+1, l = mid+1, m = 0;
        long[] cache = new long[end-start+1];
        for(int i=start; i<=mid; ++i){
            while(j<=end && array[j]-array[i]<lower) j++;
            while(k<=end && array[k]-array[i]<=upper) k++;
            count += k-j;
            while(l<=end && array[l]<=array[i]) cache[m++] = array[l++];
            cache[m++] = array[i];
        }

        System.arraycopy(cache, 0, array, start, m);
        return count;
    }
}

Friday, January 8, 2016

LeetCode [326] Power of Three

Ref
[1] https://leetcode.com/problems/power-of-three/
OJ
[2] https://leetcode.com/discuss/78532/a-summary-of-all-solutions

Tuesday, January 5, 2016

LeetCode [325] Maximum Size Subarray Sum Equals k

325. Maximum Size Subarray Sum Equals k
Medium

Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If there isn't one, return 0 instead.

Note:
The sum of the entire nums array is guaranteed to fit within the 32-bit signed integer range.

Example 1:

Input: nums = [1, -1, 5, -2, 3], k = 3
Output: 4 
Explanation: The subarray [1, -1, 5, -2] sums to 3 and is the longest.

Example 2:

Input: nums = [-2, -1, 2, 1], k = 1
Output: 2 
Explanation: The subarray [-1, 2] sums to 1 and is the longest.

Follow Up:
Can you do it in O(n) time?

//C++: 96ms
class Solution {
public:
    int maxSubArrayLen(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> sums(n+1, 0);
        unordered_map<int, int> hash;//sum, index
        hash[0] = 0;
        int ret = 0;
        for(int i=1; i<=n; ++i){
            sums[i] = sums[i-1]+nums[i-1];
            if(hash.count(sums[i])==0) hash[sums[i]] = i;
            int diff = sums[i]-k;
            if(hash.count(diff)){
                ret = max(ret, i-hash[diff]);
            }
        }
        return ret;
    }
};

//Java
class Solution {
    public int maxSubArrayLen(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        int s = 0;
        int r = 0;
        map.put(0, -1);
        for(int i=0; i<nums.length; ++i){
            s += nums[i];
            int d = s-k;
            if(map.containsKey(d)){
                int len = i-map.get(d);
                r = Math.max(r, len);
            }
            if(!map.containsKey(s))
                map.put(s, i);
        }
        return r;
    }
}