zoukankan      html  css  js  c++  java
  • Leetcode 321.拼接最大数

    拼接最大数

    给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。

    求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。

    说明: 请尽可能地优化你算法的时间和空间复杂度。

    示例 1:

    输入:

    nums1 = [3, 4, 6, 5]

    nums2 = [9, 1, 2, 5, 8, 3]

    k = 5

    输出:

    [9, 8, 6, 5, 3]

    示例 2:

    输入:

    nums1 = [6, 7]

    nums2 = [6, 0, 4]

    k = 5

    输出:

    [6, 7, 6, 0, 4]

    示例 3:

    输入:

    nums1 = [3, 9]

    nums2 = [8, 9]

    k = 3

    输出:

    [9, 8, 9]

    首先采用分治法的思路,我们知道这K个数字中,必然有i个数组来自nums1,而剩下的k-i个数字必然来自nums2。那么问题变成从nums1中获取i个数,这i个数构成的数字最大,且这i个数字的相对位置不变。再从nums2中获取k-i个数,这k-i个数构成的数字最大,且这k-i个数字的相对位置不变。

    那么我们如何将这两个结果合并起来获得我们最终的结果呢?这里很像归并算法的merge过程,我们从两个数组的开头获取最大的值加进来呗。那如果出现相同的值怎么办?那么继续比较,直到遇到第一个不相同的数字,然后选择数字较大的那个数组。

     1 public class Solution {
     2     private int[] max(int[] nums, int k) {
     3         int[] max = new int[k];
     4         for(int i=0, j=0; i<nums.length; i++) {
     5             while (j>0 && k-j<nums.length-i && max[j-1]<nums[i]) j--;
     6             if (j<k) max[j++] = nums[i];
     7         }
     8         return max;
     9     }
    10 
    11     private int[] merge(int[] nums1, int[] nums2) {
    12         int[] merged = new int[nums1.length+nums2.length];
    13         for(int i=0, j=0, m=0; m<merged.length; m++) {
    14             merged[m] = greater(nums1, i, nums2, j) ? nums1[i++] : nums2[j++];
    15         }
    16         return merged;
    17     }
    18 
    19     private boolean greater(int[] nums1, int i, int[] nums2, int j) {
    20         while (i<nums1.length && j<nums2.length && nums1[i]==nums2[j]) {
    21             i++;
    22             j++;
    23         }
    24         return j==nums2.length || (i<nums1.length && nums1[i]>nums2[j]);
    25     }
    26 
    27     public int[] maxNumber(int[] nums1, int[] nums2, int k) {
    28         int[] max = null;
    29         for(int i=Math.max(k-nums2.length, 0); i<=Math.min(nums1.length, k); i++) {
    30             int[] merged = merge(max(nums1, i), max(nums2, k-i));
    31             if (max == null || greater(merged, 0, max, 0)) max = merged;
    32         }
    33         return max;
    34     }
    35 }


  • 相关阅读:
    【Codechef】Chef and Bike(二维多项式插值)
    USACO 完结的一些感想
    USACO 6.5 Checker Challenge
    USACO 6.5 The Clocks
    USACO 6.5 Betsy's Tour (插头dp)
    USACO 6.5 Closed Fences
    USACO 6.4 Electric Fences
    USACO 6.5 All Latin Squares
    USACO 6.4 The Primes
    USACO 6.4 Wisconsin Squares
  • 原文地址:https://www.cnblogs.com/kexinxin/p/10235203.html
Copyright © 2011-2022 走看看