zoukankan      html  css  js  c++  java
  • LeetCode-Create Maximum Number

    Given two arrays of length m and n with digits 0-9 representing two numbers. Create the maximum number of length k <= m + n from digits of the two. The relative order of the digits from the same array must be preserved. Return an array of the k digits. You should try to optimize your time and space complexity.

    Example 1:

    nums1 = [3, 4, 6, 5]
    nums2 = [9, 1, 2, 5, 8, 3]
    k = 5
    return [9, 8, 6, 5, 3]

    Example 2:

    nums1 = [6, 7]
    nums2 = [6, 0, 4]
    k = 5
    return [6, 7, 6, 0, 4]

    Example 3:

    nums1 = [3, 9]
    nums2 = [8, 9]
    k = 3
    return [9, 8, 9]

    Credits:
    Special thanks to @dietpepsi for adding this problem and creating all test cases.

     Analysis:

    The solution is inspired by @dietpepsi and @chellya based on the following posts:
    [1]: https://discuss.leetcode.com/topic/32272/share-my-greedy-solution
    [2]: https://discuss.leetcode.com/topic/36805/c-16ms-fastest-beats-97

    I used optimization introduced in [2] and the merge method introduced in [1].

    To summarize:

    1. We can find the max number with length X (named maxNumLenX) from an array nums using stack method. [1][2]
    2. Based on maxNumLenX, we can find max numbers with length of X-1, X-2, ..., 1. [2].
    3. Based on 1. and 2., we can solve the problem like this:
      a. Find maxNum2 with max possible length from nums2.
      b. Find all max numbers with less length to the min possible length.
      c. Try maxNum1 with every possible length, starting from the max possible length; Directly fetch the corresponding maxNum2 (maxNum1.length + maxNum2.length ==k), merge them and generate the results.
      d. When generating maxNum1 with length X in the loop, we can generate it from maxNum1 with length X+1.

    NOTE:

    DP solution is like this:

    dp[i][j][k]: the max number with length k, using nums1[0..i] and nums2[0...j].

    dp[i][j][k] = max{ dp[i-1][j][k], dp[i][j-1][k], (nums1[i]+dp[i-1][j][k-1]), (nums2[j]+dp[i][j-1][k-1])}.

    While the greedy solution is really hard to figure out in a short time, the DP solution is much easier to derive.

    Solution:

    public class Solution {
        public int[] maxNumber(int[] nums1, int[] nums2, int k) {
            if (k==0) return new int[k];
            if (nums1.length==0){
                return getMaxNumberFromNums(nums2,k);
            }
            if (nums2.length==0){
                return getMaxNumberFromNums(nums1,k);
            }
    
            // Generates the max number of nums2 with the max possible length.
            int[] maxNum2 = getMaxNumberFromNums(nums2,Math.min(nums2.length,k));
            
            // Generates the max number of nums2 of each possible length.
            Deque<int[]> maxNums2 = getMaxNumsForAllLenth(maxNum2,Math.max(k-nums1.length, 0));
            
            
            int[] maxNum1 = getMaxNumberFromNums(nums1,Math.min(nums1.length,k));
            int[] res = new int[k];
            for (int len1 = Math.min(nums1.length,k);len1>=Math.max(k-nums2.length,0);len1--){
                if (len1 < Math.min(nums1.length,k)){
                    maxNum1 = getMaxNumWithOneLessLen(maxNum1);
                }
                maxNum2 = maxNums2.pollFirst();
                res = getNewMaxNumber(res,maxNum1,maxNum2);
            }
            return res;
        }
        
        // Get max number with length of maxNumLen from nums.
        public int[] getMaxNumberFromNums(int[] nums, int maxNumLen){
            int[] maxNum = new int[maxNumLen];
            int len = nums.length;
            int end = 0;
            for (int i=0;i<len;i++){
                while (end >= 1 && maxNum[end-1] < nums[i] && len - i > maxNumLen - end){
                    end--;
                }
                if (end < maxNumLen) maxNum[end++] = nums[i];
            }
            return maxNum;
        }
    
        // Get max numbers with length of maxNum.length, maxNum.length-1, ..., minLen, based on maxNum.
        public Deque<int[]> getMaxNumsForAllLenth(int[] maxNum, int minLen){
            Deque<int[]> maxNums = new LinkedList<int[]>();
            maxNums.add(maxNum);
            while (maxNum.length>minLen){
                int[] nextNum = getMaxNumWithOneLessLen(maxNum);
                maxNums.addFirst(nextNum);
                maxNum = nextNum;
            }
            return maxNums;
        }
    
        // Get the max number with length of  maxNum.length-1 from maxNum.
        public int[] getMaxNumWithOneLessLen(int[] maxNum){
            int len = maxNum.length, end = 0;
            int[] nextNum = new int[len-1];
            boolean deleted = false;
            for (int i=0;i<len;i++){
                if (end >= len-1) break;
                if ((i==len-1 || maxNum[i] >= maxNum[i+1]) || deleted){
                    nextNum[end++] = maxNum[i];                
                } else {
                    deleted = true;
                }                
            }     
            return nextNum;
        }
    
        // Merge part1 and part2 into a new max number, substitute the old one if the new one is larger. 
        public int[] getNewMaxNumber(int[] maxNum, int[] part1, int[] part2){
            int[] newNum = new int[maxNum.length];
            int p1 = 0, p2 = 0, index = 0;
            boolean newNumLarger = false;
            while (p1 < part1.length || p2 < part2.length){
                newNum[index] = (greater(part1,p1,part2,p2)) ? part1[p1++] : part2[p2++];
                
                // Early termination, if we find new number is less than the existing one.
                if (maxNum[index] > newNum[index] && !newNumLarger){
                    return maxNum;
                } else if (maxNum[index] < newNum[index]){
                    newNumLarger = true;
                }
                index++;
            }
            return newNum;
        }
        
        // This is function is important. When merging two parts into the max number, we need address the case part1[p1] == part2[p2].
        public boolean greater(int[] part1, int p1, int[] part2, int p2){
            while (p1<part1.length && p2<part2.length && part1[p1]==part2[p2]){
                p1++;
                p2++;
            }
            
            return p2==part2.length || (p1 < part1.length && part1[p1] > part2[p2]);
        }
    }
  • 相关阅读:
    Left Join
    SQL not exists双重否定
    修改页面下拉框的数据绑定为表里的数据
    myeclipse 项目运行时报错:运行项目时报错:Could not publish server configuration for Tomcat v6.0 Server at localhost. Multiple Contexts have a"/"
    关于js效果不提示就执行了刷新(解决 在hui框架中)
    使用 fn 标签 解决字数过多时用省略号代替 .............................
    java 优化
    java 使用substring 截取特殊字符串的后一位或者数字
    jsp页面 使用c 标签的 varStatus 属性和 index 解决一行显示多少个 然后进行自动换行
    jsp 页面通过jq处理默认 选中的项 数据是通过遍历显示
  • 原文地址:https://www.cnblogs.com/lishiblog/p/5838597.html
Copyright © 2011-2022 走看看