2015年11月3日星期二

Leetcode 221 Maximal Square

Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and return its area.
For example, given the following matrix:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 4.
Solution 1: Use DP. dp[i][j] is the max length if matrix[i][j] is the bottom right corner of the square. (1) if matrix[i][j] is 0, dp[i][j]=0; (2) if matrix[i][j]=1, we need to check dp[i-1][j] and dp[i][j-1]; (2a) if they are different, it is smaller of the two plus 1. (2b) check if they are equal, say dp[i-1][j]=dp[i][j-1]=len, check if weather dp[i-len][j-len] is 0 or 1.
 public class Solution {  
   public int maximalSquare(char[][] matrix) {  
     int m=matrix.length;  
     if (m==0) return 0;  
     int n=matrix[0].length;  
     int[] dp=new int[n];  
     int res=0;  
     for (int i=0; i<m; i++) {  
       for (int j=0; j<n; j++) {  
         if (matrix[i][j]=='0') dp[j]=0;  
         else if (i==0 || j==0) dp[j]=1;  
         else if (dp[j]==dp[j-1]) {  
           int k=dp[j];  
           dp[j]=(matrix[i-k][j-k]=='0')?k:k+1;  
         }  
         else dp[j]=1+Math.min(dp[j-1],dp[j]);  
         res=Math.max(res,dp[j]);  
       }  
     }  
     return res*res;  
   }  
 }  

Leetcode 220 Contains Duplicate III

Given an array of integers, find out whether there are two distinct indices i and j in the array such that the difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.
Solution 1: compare to II, use Tree Map instead of Hashmap could solve it.
 public class Solution {  
   public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {  
     int n=nums.length, i=0;  
     if (t<0) return false;  
     TreeSet<Integer> set=new TreeSet<>();  
     for (int j=0; j<n; j++) {  
       if (j-i>k) set.remove(nums[i++]);  
       int lo=(nums[j]<Integer.MIN_VALUE+t)?Integer.MIN_VALUE:nums[j]-t;  
       int hi=(nums[j]>Integer.MAX_VALUE-t)?Integer.MAX_VALUE:nums[j]+t;  
       if (set.ceiling(lo)!=null && set.ceiling(lo)<=hi) return true;  
       set.add(nums[j]);  
     }  
     return false;  
   }  
 }  

Leetcode 219 Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and jis at most k.
Solution 1:  Use hash table and slide window
 public class Solution {  
   public boolean containsNearbyDuplicate(int[] nums, int k) {  
     Set<Integer> set=new HashSet<>();  
     int i=0;  
     for (int j=0; j<nums.length; j++) {  
       if (j-i>k) set.remove(nums[i++]);  
       if (set.contains(nums[j])) return true;  
       set.add(nums[j]);  
     }  
     return false;  
   }  
 }  

Leetcode 218 The Skyline Problem

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B).
Buildings Skyline Contour
The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.
For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] .
The output is a list of "key points" (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.
For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ].
Notes:
  • The number of buildings in any input list is guaranteed to be in the range [0, 10000].
  • The input list is already sorted in ascending order by the left x position Li.
  • The output list must be sorted by the x position.
  • There must be no consecutive horizontal lines of equal height in the output skyline. For instance, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...[2 3], [4 5], [12 7], ...]
Solution 1: Use divide and conquer. Each time combine to sub skyline. When the sub skyline is just one building, it is just top left and bottom right point. The difficult part is how to combine the two sky line list.
 public class Solution {  
   public List<int[]> getSkyline(int[][] buildings) {  
     int n=buildings.length;  
     return getSkyline(buildings,0,n-1);  
   }  
   private List<int[]> getSkyline(int[][] buildings, int lo, int hi) {  
     List<int[]> res=new ArrayList<>();  
     if (lo>hi) return res;  
     else if (lo==hi) {  
       int[] p1=new int[]{buildings[lo][0],buildings[lo][2]};  
       int[] p2=new int[]{buildings[lo][1],0};  
       res.add(p1);  
       res.add(p2);  
     }  
     else {  
       int mid=lo+(hi-lo)/2;  
       List<int[]> l1=getSkyline(buildings,lo,mid);  
       List<int[]> l2=getSkyline(buildings,mid+1,hi);  
       int i=0, j=0;  
       int m=l1.size(), n=l2.size();  
       while (i<m || j<n) {  
         if (i>=m) res.add(l2.get(j++));  
         else if (j>=n) res.add(l1.get(i++));  
         else {  
           int x=0;  
           if (l1.get(i)[0]<l2.get(j)[0]) x=l1.get(i++)[0];  
           else if (l1.get(i)[0]>l2.get(j)[0]) x=l2.get(j++)[0];  
           else {  
             x=l1.get(i)[0];  
             i++;j++;  
           }  
           int y=getHight(l1,l2,i-1,j-1);  
           int size=res.size();  
           if (size==0 || y!=res.get(size-1)[1]) res.add(new int[]{x,y});  
         }  
       }  
     }  
     return res;  
   }  
   private int getHight(List<int[]> l1, List<int[]> l2, int i, int j) {  
     if (i<0) return l2.get(j)[1];  
     else if (j<0) return l1.get(i)[1];  
     else return Math.max(l1.get(i)[1],l2.get(j)[1]);  
   }  
 }  

Leetcode 217 Contains Duplicate

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.
Solution 1: easy hash problem
 public class Solution {  
   public boolean containsDuplicate(int[] nums) {  
     Set<Integer> set=new HashSet<>();  
     for (int x:nums) {  
       if (set.contains(x)) return true;  
       else set.add(x);  
     }  
     return false;  
   }  
 }  

Leetcode 216 Combination Sum III

Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
Ensure that numbers within the set are sorted in ascending order.

Example 1:
Input: k = 3, n = 7
Output:
[[1,2,4]]

Example 2:
Input: k = 3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
Solution 1: Use back tracking method. Terminate condition is (1) reach depth of k, generate possible result. (2) num>9 not valid, (3) num>n, not valid as in ascending  order.
 public class Solution {  
   public List<List<Integer>> combinationSum3(int k, int n) {  
     List<List<Integer>> res=new ArrayList<>();  
     if (k>9 || k<0) return res;  
     if (n<1 || n>45) return res;  
     List<Integer> one=new ArrayList<>();  
     dfs(0,1,k,n,one,res);  
     return res;  
   }  
   private void dfs(int d, int num, int k, int n, List<Integer> one, List<List<Integer>> res) {  
     if (d==k) {  
       if (n==0) res.add(new ArrayList<Integer>(one));  
     }  
     else if (num<=9 && num<=n) {  
       dfs(d,num+1,k,n,one,res);  
       one.add(num);  
       dfs(d+1,num+1,k,n-num,one,res);  
       one.remove(one.size()-1);  
     }  
   }  
 }  

Leetcode 215 Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4] and k = 2, return 5.
Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.
Solution 1: Sort the array and return nums[k-1], it is O(nlogn) time and O(1) space.
Solution 2: QuickSort partition. O(n) best and O(n^2) worst. Can be shuffle to grantee the performance
 public class Solution {  
   public int findKthLargest(int[] nums, int k) {  
     k--;  
     int lo=0, hi=nums.length-1;  
     while (lo<=hi) {  
       int[] p=partition(nums,lo,hi);  
       if (k>p[1]) lo=p[1]+1;  
       else if (k<p[0]) hi=p[0]-1;  
       else return nums[k];  
     }  
     return 0;  
   }  
   private int[] partition(int[] nums, int lo, int hi) {  
     int v=nums[lo];  
     int j=lo, i=lo+1, k=hi;  
     while (i<=k) {  
       if (nums[i]==v) i++;  
       else if (nums[i]<v) swap(nums,i,k--);  
       else swap(nums,i++,j++);  
     }  
     return new int[]{j,k};  
   }  
   private void swap(int[] nums, int i, int j) {  
     int temp=nums[i];  
     nums[i]=nums[j];  
     nums[j]=temp;  
   }  
 }