// Source : https://leetcode.com/problems/create-maximum-number/ // Author : Hao Chen // Date : 2016-01-21 /*************************************************************************************** * * Given two arrays of length m and n with digits 0-9 representing two numbers. * Create the maximum number of length k 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. ***************************************************************************************/ /* * Solution * -------- * * 1) We split the `K` to two parts : `i` & `k-i` 0<= i <= k * * 2) Find the max number for both arrays with giving the length `i` and `k-i` * - sub1 = FindMaxNumber(num1, len=i); * - sub2 = FindMaxNumber(num2, len=k-i); * Here, we need use stack-way to solve find the max number. * * 3) Merge two arrays * - solution = Merge(sub1, sub2); * Here, we need be careful if a two number are same which one we need to take. For examples: * [6,7] * [6,0,4] * 5 * * [2,5,6,4,4,0] * [7,3,8,0,6,5,7,6,2] * 15 * * 4) compare with the last solution * - result = max(result, solution); * * */ class Solution { public: vector maxNumber(vector& nums1, vector& nums2, int k) { vector result; int len1 = nums1.size(); int len2 = nums2.size(); for (int i=0; i<=k; i++){ if (len1 < i || len2 < k-i) continue; vector sub1 = findMaxSubArray(nums1, i); vector sub2 = findMaxSubArray(nums2, k-i); vector merge = mergeTwoArrays(sub1, sub2); if (compareTwoArray(merge, 0, result, 0)) { result = merge; } } return result; } bool compareTwoArray(vector& nums1, int start1, vector& nums2, int start2) { int n1 = nums1.size(); int n2 = nums2.size(); for(; start1 nums2[start2]) return true; if (nums1[start1] < nums2[start2]) return false; } //if num1 still have numbers, return true, else return false return start1 < nums1.size(); } vector mergeTwoArrays(vector& nums1, vector& nums2) { vector result; int len1 = nums1.size(); int len2 = nums2.size(); int pos1=0, pos2=0; while ( pos1 < len1 && pos2 < len2 ){ // Be careful if two numbers are equal. consider the following case // case 1: [6,7], [6,0,4] - we have same item - 6 // case 2: [4,0,2], [2,0,3,1] - we have same item - 0 // which one we need to merge? // We need compare the rest of array. if (nums1[pos1] == nums2[pos2]){ result.push_back( compareTwoArray(nums1, pos1+1, nums2, pos2+1) ? nums1[pos1++] : nums2[pos2++]); }else { result.push_back(nums1[pos1] > nums2[pos2] ? nums1[pos1++] : nums2[pos2++]); } } if (pos1 < len1){ result.insert(result.end(), nums1.begin()+pos1, nums1.end()); } if (pos2 < len2) { result.insert(result.end(), nums2.begin()+pos2, nums2.end()); } return result; } // using a stack method to find the max sub-array // k <= nums.size() vector findMaxSubArray(vector& nums, int k) { int len = nums.size(); if ( k >= len ) return nums; vector result(k, 0); int idx = 0; // the postion for result array for (int i=0; i the last element of result[], // and we still have enough numbers, // then pop up the item while (idx>0 && k - idx < len - i && result[idx-1] < nums[i]) { idx--; } //push the number into the result[] if (idx < k) { result[idx++] = nums[i]; } } return result; } };