Thursday, October 26, 2017

341. Flatten Nested List Iterator

Given a nested list of integers, implement an iterator to flatten it.
Each element is either an integer, or a list -- whose elements may also be integers or other lists.
Example 1:
Given the list [[1,1],2,[1,1]],
By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,1,2,1,1].
Example 2:
Given the list [1,[4,[6]]],
By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,4,6].

Solution:
Iterative: Stack
Use a stack to maintain all the flattened integer. If the current nestedInteger is a list, we push its elements(last->first) to the stack. Make sure all the elements in the stack are integers.

 public class NestedIterator implements Iterator<Integer> {  
   Stack<NestedInteger> st;  
   public NestedIterator(List<NestedInteger> nestedList) {  
     st=new Stack<NestedInteger>();  
     for(int i=nestedList.size()-1;i>=0;i--){  
       st.push(nestedList.get(i));  
     }  
   }  
   @Override  
   public Integer next() {  
     return st.pop().getInteger();  
   }  
   @Override  
   public boolean hasNext() {      
     while(!st.empty() && !st.peek().isInteger()){  
       List<NestedInteger> li=st.pop().getList();  
        for(int i=li.size()-1;i>=0;i--){  
       st.push(li.get(i));  
     }  
     }  
      if(st.empty()) return false;  
     return true;  
   }  
 }  

Another solution is kind of recursive solution. We recursively use the NestedIterator to iterate nested list. Backtrack to current list when the next iterator doesn't have next element.

 public class NestedIterator implements Iterator<Integer> {  
   NestedIterator nextIt;  
   Iterator<NestedInteger> itr;  
   Integer nextInt;  
   public NestedIterator(List<NestedInteger> nestedList) {  
     itr=nestedList.iterator();  
     nextIt=null;  
     nextInt=null;  
   }  
   @Override  
   public Integer next() {  
     if(nextIt!=null) return nextIt.next();  
     return nextInt;  
   }  
   @Override  
   public boolean hasNext() {  
     if(nextIt!=null && nextIt.hasNext()) return true;  
     while(itr.hasNext()){  
       NestedInteger nextNestedInteger=itr.next();  
       nextIt=null;  
       if(nextNestedInteger.isInteger()){  
         nextInt=nextNestedInteger.getInteger();  
         return true;  
       }  
       else{  
         nextIt=new NestedIterator(nextNestedInteger.getList());  
         if(nextIt.hasNext()) return true;  
       }  
     }  
     return false;  
   }  
 }  

Saturday, October 21, 2017

350. Intersection of Two Arrays II

Given two arrays, write a function to compute their intersection.
Example:
Given nums1 = [1, 2, 2, 1]nums2 = [2, 2], return [2, 2].
Note:
  • Each element in the result should appear as many times as it shows in both arrays.
  • The result can be in any order.
Follow up:
  • What if the given array is already sorted? How would you optimize your algorithm?
  • What if nums1's size is small compared to nums2's size? Which algorithm is better?
  • What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?
Solution:
Use a hashmap to maintain all the number and its occurrences. Iterate nums2, if map contains the number and the occurrences is greater than 0, add to the result list and decrease the occurrences in the map.

If the array is sorted, we can use two pointers and increment the smaller one until the two numbers are equal, add the number to the result list, increment both pointers.

 public int[] intersect(int[] nums1, int[] nums2) {  
     HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();  
     for(int i=0;i<nums1.length;i++){  
       map.put(nums1[i],map.getOrDefault(nums1[i],0)+1);  
     }  
     List<Integer> list=new ArrayList<Integer>();  
     for(int i=0;i<nums2.length;i++){  
       if(map.containsKey(nums2[i]) && map.get(nums2[i])>0){  
         list.add(nums2[i]);  
         map.put(nums2[i],map.get(nums2[i])-1);  
       }  
     }  
     int[] res=new int[list.size()];  
     for(int i=0;i<list.size();i++){  
       res[i]=list.get(i);  
     }  
     return res;  
   }  

349. Intersection of Two Arrays

Given two arrays, write a function to compute their intersection.
Example:
Given nums1 = [1, 2, 2, 1]nums2 = [2, 2], return [2].
Note:
  • Each element in the result must be unique.
  • The result can be in any order.

Solution:
Use a hashset to maintain all the integers int nums1, then check if nums2 also have those integers, if yes, add to the result list.

I am not sure if there are more advanced solution out there.


 public int[] intersection(int[] nums1, int[] nums2) {  
     HashSet<Integer> set=new HashSet<Integer>();  
     for(int i=0;i<nums1.length;i++){  
       set.add(nums1[i]);  
     }  
     List<Integer> list=new ArrayList<Integer>();  
     for(int i=0;i<nums2.length;i++){  
       if(set.contains(nums2[i])){  
         list.add(nums2[i]);  
         set.remove(nums2[i]);  
       }  
     }  
     int[] res=new int[list.size()];  
     for(int i=0;i<list.size();i++){  
       res[i]=list.get(i);  
     }  
     return res;  
   }  

345. Reverse Vowels of a String

Write a function that takes a string as input and reverse only the vowels of a string.
Example 1:
Given s = "hello", return "holle".
Example 2:
Given s = "leetcode", return "leotcede".
Note:
The vowels does not include the letter "y".

Solution:
Convert the string to a char array, then use one pointer to find vowels from left to right, and use another pointer to find vowels from right to left. Swap vowels when we process the char array.
Time complexity: O(n)

 public String reverseVowels(String s) {  
     char[] sarr=s.toCharArray();  
     int i=0;  
     int j=sarr.length-1;  
     while(i<j){  
       while(i<j && !isVowel(sarr[i])) i++;  
       while(i<j && !isVowel(sarr[j])) j--;  
       char c=sarr[i];  
       sarr[i++]=sarr[j];  
       sarr[j--]=c;  
     }  
     return new String(sarr);  
   }  
   public boolean isVowel(char c){  
     return c=='a'||c=='e'||c=='i'||c=='o'||c=='u'  
       || c=='A'||c=='E'||c=='I'||c=='O'||c=='U';  
   }  

344. Reverse String

Write a function that takes a string as input and returns the string reversed.
Example:
Given s = "hello", return "olleh".

Solution:
There are so many solutions:
Stringbuilder, charArray ....
 public String reverseString(String s) {  
     return new StringBuilder(s).reverse().toString();  
   }  
  public String reverseString(String s) {  
     StringBuilder sb=new StringBuilder();  
     for(int i=s.length()-1;i>=0;i--) sb.append(s.charAt(i));  
     return sb.toString();  
   }  

343. Integer Break

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.
For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
Note: You may assume that n is not less than 2 and not larger than 58.

Solution:
Dynamic programming.
The tricky part is for number 1, 2 and 3,which the break product is smaller than itself. 
So any number that break into 2 or 3 should use the number itself instead of dp[2] or dp[3]. (dp[1]=0, dp[2]=1, dp[3] =2)
dp[i] =Math.max (dp[i], dp[j]*dp[i-j]) if j >=4 and j-i >=4.

 public int integerBreak(int n) {  
     int[] dp=new int[n+1];  
     for(int i=2;i<=n;i++){  
       for(int j=1;j<=i/2;j++){  
         dp[i]=Math.max(dp[i],Math.max(j,dp[j])*Math.max(i-j,dp[i-j]));  
       }        
     }  
     return dp[n];  
   }  

331. Verify Preorder Serialization of a Binary Tree

One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record the node's value. If it is a null node, we record using a sentinel value such as #.
     _9_
    /   \
   3     2
  / \   / \
 4   1  #  6
/ \ / \   / \
# # # #   # #
For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a null node.
Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a binary tree. Find an algorithm without reconstructing the tree.
Each comma separated value in the string must be either an integer or a character '#' representing null pointer.
You may assume that the input format is always valid, for example it could never contain two consecutive commas such as "1,,3".
Example 1:
"9,3,4,#,#,1,#,#,2,#,6,#,#"
Return true
Example 2:
"1,#"
Return false
Example 3:
"9,#,#,1"
Return false
Solution:
Level traverse, the number of non-null node determines the number of next level nodes.
Using the example in the question,
Level 1 has 1 non-null node, so level 2 should have 2 nodes,
Level 2 has 2 non-null nodes, so level 3 should have 4 nodes,
Level 3 has 3 non-null nodes, so level 4 should have 6 nodes,
level 5 has 0 non-null nodes, so level 6 should be empty.
So we can use a count variable to keep track how many nodes we will have to next level,
So for the first level we should have count =1,
because there is 1 non-null node, count+=2, means there will be 3 in total of node to level 2,
We keep the iteration until we either hit the last node or we hit the total counts.
So if the total count to the last level is the same as the total number of nodes, which means the string is a valid preorder serialization. False otherwise.
Time complexity: O(n)
 public boolean isValidSerialization(String preorder) {  
     if(preorder==null || preorder.length()==0) return false;  
     String[] nodes=preorder.split(",");  
     int count=1;  
     for(int i=0;i<nodes.length && i<count;i++){  
       if(!nodes[i].equals("#")) count+=2;  
     }  
     return count==nodes.length;  
   }  

Thursday, October 19, 2017

335. Self Crossing

You are given an array x of n positive numbers. You start at point (0,0) and moves x[0] metres to the north, then x[1] metres to the west, x[2] metres to the south, x[3] metres to the east and so on. In other words, after each move your direction changes counter-clockwise.
Write a one-pass algorithm with O(1) extra space to determine, if your path crosses itself, or not.
Example 1:
Given x = [2, 1, 1, 2],
?????
?   ?
???????>
    ?

Return true (self crossing)
Example 2:
Given x = [1, 2, 3, 4],
????????
?      ?
?
?
?????????????>

Return false (not self crossing)
Example 3:
Given x = [1, 1, 1, 1],
?????
?   ?
?????>

Return true (self crossing)
Solution:
Obviously, if the array length is smaller than 4, it never cross it self.
Line 3 can only cross line 0 when line 2 is <= line 0 && line 3 >=line 1
Line 4 can cross line 1 and also cross line 0, 
    a. For crossing line 1, it is the same situation with line 3 crossing line 0: x[i-1]<=x[i-3] && x[i]>=x[i-2]
   b. For crossing line 0, line3== line 1 and line 4 >= line2-line0 =>x[i-1]==x[i-3] && x[i]>=x[i-2]-x[i-4]. 
Line 5 can cross line 2 and line 0
   a. For crossing line 2, it is the same: x[i-1]<=x[i-3] && x[i]>=x[i-2]
   b. For crossing line 0,  Line 2 > line 0, && line 3 must > line 1, line 4 must between lin2-line 0 and line 2, then line 5 must > line 3-line 1 => x[i-2]>x[i-4] && x[i-1]>=x[i-3]-x[i-5] && x[i-1]<=x[i-3] && x[i]>=x[i-2]-x[i-4].
 You will get a more clear picture if you draw it on a paper. 
For any line > 5, basically it is the same with line 5, you can rotate your drawing and you will understand why it is the same. 

 public boolean isSelfCrossing(int[] x) {  
     if(x==null || x.length<4) return false;  
     for(int i=3;i<x.length;i++){  
       if(x[i-1]<=x[i-3] && x[i]>=x[i-2]) return true;  
       if(i==4 && x[i-1]==x[i-3] && x[i]>=x[i-2]-x[i-4]) return true;  
       if(i>=5 && x[i-2]>x[i-4] && x[i-1]>=x[i-3]-x[i-5] && x[i-1]<=x[i-3] && x[i]>=x[i-2]-x[i-4]) return true;  
     }  
     return false;  
   }  

334. Increasing Triplet Subsequence

Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.
Formally the function should:
Return true if there exists i, j, k 
such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.
Your algorithm should run in O(n) time complexity and O(1) space complexity.
Examples:
Given [1, 2, 3, 4, 5],
return true.
Given [5, 4, 3, 2, 1],
return false.

Solution:
Use two variables num1 and num2 to keep track current increasing subsequence. keep num1 < num2, If we find any element that is greater than num2, which means we found an increasing subsequence of length 3. If we find a number that is between num1 and num2, we update num2 to current number which make the third element easier to achieve. If we find a number is less then num1, update num1 as we can lower num2 and the third element thereafter. 

 public boolean increasingTriplet(int[] nums) {  
     if(nums==null || nums.length<3) return false;  
     int num1=nums[0];  
     int num2=Integer.MAX_VALUE;  
     for(int i=1;i<nums.length;i++){  
       if(nums[i]>num2) return true;  
       if(nums[i]<num1) num1=nums[i];  
       else if(nums[i]>num1 && nums[i]<num2) num2=nums[i];  
     }  
     return false;  
   }  

Sunday, October 15, 2017

342. Power of Four

Given an integer (signed 32 bits), write a function to check whether it is a power of 4.
Example:
Given num = 16, return true. Given num = 5, return false.
Follow up: Could you solve it without loops/recursion?

Solution:
First of all, power of 4 should be also power of 2, The only difference is 
1. Power of 4 is a perfect square number while power of 2 is not.
 public boolean isPowerOfFour(int num) {  
     int a=(int)Math.sqrt(num);  
     return (num>0 && (num&(num-1))==0 && a*a==num );   
   }  

2. (Power of 4 -1) can be divided by 3 while power of 2 cannot.
 public boolean isPowerOfFour(int num) {  
     return (num>0 && (num&(num-1))==0 && (num-1)%3==0 );   
   }  

338. Counting Bits

Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.
Example:
For num = 5 you should return [0,1,1,2,1,2].
Follow up:
  • It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
  • Space complexity should be O(n).
  • Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
Solution:
1. DP
   1.Obviously, count[1111] = count[1000]+count[111]
   2. And any number that is power of 2 should have only 1 of digit 1. Like 1,10,100...
   3. Besides those power of 2 numbers, all others should follow the first observation.
2. DP
   1. Count[1111] = count[111] + count[1], count[1110] = count[111]+count[0]
    => count[n] = count[n/2]+count[n%2] or count[n]=count[n>>1]+count[n&1]

   
 public int[] countBits(int num) {  
     int[] res=new int[num+1];  
     int factor=1;  
     for(int i=1;i<=num;i++){  
       if((i &(i-1))==0){  
         factor=i;  
       }  
       res[i]=res[i%factor]+1;  
     }  
     return res;  
   }  
 public int[] countBits(int num) {  
     int[] res=new int[num+1];  
     for(int i=1;i<res.length;i++){  
       res[i] = res[i/2] + (i %2);  
     }  
     return res;  
   }  

337. House Robber III

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.
Determine the maximum amount of money the thief can rob tonight without alerting the police.
Example 1:
     3
    / \
   2   3
    \   \ 
     3   1
Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
     3
    / \
   4   5
  / \   \ 
 1   3   1
Maximum amount of money the thief can rob = 4 + 5 = 9.

Solution:
Similar with all previous House Robber problem, each node may have two states, robbed, not robbed,
Constrains:
If current node is robbed, we can't rob its children. 
If current node is not robbed, we can either rob or not rob its children depends on which option gives us the maximum profit. 
Recursion to get the maximum money.


 public int rob(TreeNode root) {  
     int[] res=getMoney(root);  
     return Math.max(res[0],res[1]);  
   }  
   public int[] getMoney(TreeNode root){  
     if(root==null) return new int[2];  
     int[] left=getMoney(root.left);  
     int[] right=getMoney(root.right);  
     int[] res=new int[2];  
     res[0]=root.val+left[1]+right[1];  
     res[1]=Math.max(left[0],left[1])+Math.max(right[0],right[1]);  
     return res;  
   }   

332. Reconstruct Itinerary

Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus, the itinerary must begin with JFK.
Note:
  1. If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary ["JFK", "LGA"] has a smaller lexical order than ["JFK", "LGB"].
  2. All airports are represented by three capital letters (IATA code).
  3. You may assume all tickets form at least one valid itinerary.
Example 1:
tickets = [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Return ["JFK", "MUC", "LHR", "SFO", "SJC"].
Example 2:
tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Return ["JFK","ATL","JFK","SFO","ATL","SFO"].
Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"]. But it is larger in lexical order.
Solution:
Classic DFS,
Create a map to maintain the mapping for departure city and all arrival cities, sort all arrived cities because we need the result to have the smallest lexical order.
DFS from JFK, set the destiny city as "#" to mark it as visited, return result when it covers all the egdes, because we sorted all the destiny cities before hand, the first valid result are guaranteed to be the smallest one. 
 public List<String> findItinerary(String[][] tickets) {  
     HashMap<String,List<String>> map=new HashMap<String,List<String>>();  
     for(int i=0;i<tickets.length;i++){  
       if(!map.containsKey(tickets[i][0])) map.put(tickets[i][0],new ArrayList<String>());  
       map.get(tickets[i][0]).add(tickets[i][1]);  
     }  
     for(List<String> item: map.values()){  
       Collections.sort(item);  
     }  
     List<String> res=new ArrayList<String>();  
     DFSHelper(map,"JFK",tickets.length+1,res);  
     return res;      
   }  
   public boolean DFSHelper(HashMap<String,List<String>> map, String cur,int n, List<String> res){  
     res.add(cur);  
     if(res.size()==n) return true;  
     if(!map.containsKey(cur)){  
       res.remove(res.size()-1);  
       return false;  
     }  
     List<String> destinations=map.get(cur);  
     for(int i=0;i<destinations.size();i++){  
       if(!destinations.get(i).equals("#")){  
         String next=destinations.get(i);  
         destinations.set(i,"#");  
         if(DFSHelper(map,next,n,res)) return true;  
         destinations.set(i,next);  
       }  
     }  
     res.remove(res.size()-1);  
    return false;  
   }  
 }  

A better and more concise solution by doing following optimization:
We can use a priorityQueue to maintain the destiny city, which could remove the individual sorting for each map.value(). In terms of time complexity, they are the same.
We can add city from tail to head because any city that doesn't have any outage degree should be added to the tail of current all unfinished cities.

Hierholzer's algorithm to solve Eulerian path (to visit all the path exactly once)

https://en.wikipedia.org/wiki/Eulerian_path
Keep going forward until you get stuck, add the stuck point to the list then backtrack and repeat till all nodes have degree of 0.
   
  public List<String> findItinerary(String[][] tickets) {  
     HashMap<String,PriorityQueue<String>> map=new HashMap<String,PriorityQueue<String>>();  
     int n=tickets.length;  
     for(int i=0;i<n;i++){  
       if(!map.containsKey(tickets[i][0])) map.put(tickets[i][0],new PriorityQueue<String>());  
       map.get(tickets[i][0]).offer(tickets[i][1]);  
     }  
     List<String> res=new LinkedList<String>();  
     dfsHelper(res,map,"JFK");  
     return res;  
   }  
   public void dfsHelper(List<String> res, HashMap<String,PriorityQueue<String>> map, String airport){  
     while(map.containsKey(airport)&& map.get(airport).size()!=0){  
       dfsHelper(res,map,map.get(airport).poll());  
     }  
     res.add(0,airport);  
   }  

329. Longest Increasing Path in a Matrix

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:
nums = [
  [9,9,4],
  [6,6,8],
  [2,1,1]
]
Return 4
The longest increasing path is [1, 2, 6, 9].
Example 2:
nums = [
  [3,4,5],
  [3,2,6],
  [2,2,1]
]
Return 4
The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.

Solution:
DFS and dynamic programming.
We can calculate all the maximum length for all cells if the path start at the current cell using DFS. 
So if his neighbor is greater than the current cell, we DFS to its neighbors, and find the max for all 4 directions.
If we only do DFS, we can't pass the time limit, because we actully calculate some cells multiple times.
For example:
nums = [
  [3,4,5],
  [1,2,6],
  [7,8,9]
]
Cell 4 will be visited twice, first as the right neighbor of element 3 and then as the top element of cell 2. We need a array to keep all visited values,
If the element is visited, we can simply apply the maximum length rather than run DFS again from that cell.
The maxLength of current element would be maximum of all qualified neighbors + 1.


  public int longestIncreasingPath(int[][] matrix) {  
     if(matrix==null || matrix.length==0 || matrix[0].length==0) return 0;  
     int m=matrix.length;  
     int n=matrix[0].length;  
     int res=1;  
     int[][] dp=new int[m][n];  
     for(int i=0;i<m;i++){  
       for(int j=0;j<n;j++){  
       res=Math.max(res,helper(matrix,i,j,dp));  
       }  
     }  
     return res;  
   }  
   public int helper(int[][] matrix, int i, int j, int[][] dp){  
     if(dp[i][j]!=0) return dp[i][j];  
     int res=1;  
     if(i>0 && matrix[i-1][j]>matrix[i][j]){  
       res=Math.max(helper(matrix,i-1,j,dp)+1,res);  
     }  
     if(i+1<matrix.length && matrix[i+1][j]>matrix[i][j]){  
       res=Math.max(helper(matrix,i+1,j,dp)+1,res);  
     }  
     if(j>0 && matrix[i][j-1]>matrix[i][j]){  
       res=Math.max(helper(matrix,i,j-1,dp)+1,res);  
     }  
     if(j+1<matrix[0].length && matrix[i][j+1]>matrix[i][j]){  
       res=Math.max(helper(matrix,i,j+1,dp)+1,res);  
     }  
     dp[i][j]=res;  
     return res;      
   }  

Saturday, October 14, 2017

330. Patching Array

Given a sorted positive integer array nums and an integer n, add/patch elements to the array such that any number in range [1, n]inclusive can be formed by the sum of some elements in the array. Return the minimum number of patches required.
Example 1:
nums = [1, 3]n = 6
Return 1.
Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4.
Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3].
Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].
So we only need 1 patch.
Example 2:
nums = [1, 5, 10]n = 20
Return 2.
The two patches can be [2, 4].
Example 3:
nums = [1, 2, 2]n = 5
Return 0.
Solution:
Greedy, use every possible value to increase the range.
Use the right patch to maximize the range.
Eg. If current range is [1,20], and we should add 21 to the array to maximize the range, which will make the range increase to [1,41]. We can't add any number that is larger than 21, which will make 21 not in the range. If we add any number smaller than 21, the range is not maximized.
if current range is [1,20] the next value in nums is 30, and the target is 69. We should add 21 as a patch to make range increase to [1,41], then we can use 30 to increase the range, [1,71] which will cover 69.
Time complexity: O(nums.length,+lg(n))) either we add patch each time to cover n (each time the range will double or we use the numbers in the array )

 public int minPatches(int[] nums, int n) {  
     int count=0;  
     long covered=0;  
     int i=0;  
     while(covered<n){  
       if(i>=nums.length || covered+1<nums[i]){  
         count++;  
         covered=2*covered+1;  
       }  
       else covered+=nums[i++];  
     }  
     return count;  
   }  
 }