Tuesday, September 17, 2019

Leetcode 321: Create Maximum Number

https://leetcode.com/problems/create-maximum-number/description/



Notes:

This question is hard question, as labeled.

My first method is using memorization, memo[i][j][k] represents the largest new arr with size of k by using elements starting of i-th in arr1 and j-th in arr2. But it quickly receive TLE.

It turns out it can be solved greedily. After decomposing it into two simpler sub-problems, this question becomes not that hard.

1): find a largest subsequence with a size of k from a given array;

2): merge two given arrays to form the largest sequence (including all elements).

Both sub-questions above are not hard to implemented (maybe the second one need to deal with a specific case when the first elements are equal, but it is still not hard to deal with with a short comparison function, see below).

See the code below:

  1. class Solution {
  2. public:
  3.     vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
  4.         int m = nums1.size(), n = nums2.size();
  5.         vector<int> res(k);
  6.         for(int i=max(0, k-n); i<=min(k, m); ++i) {
  7.             vector<int> v1 = find(nums1, i), v2 = find(nums2, k-i);
  8. //find i from nums1, find (k-i) from nums2
  9.             vector<int> nt = merge(v1, v2);
  10.             if(larger(nt, 0, res, 0)) res = nt;
  11.         }
  12.         return res;
  13.     }
  14. private:
  15.     vector<int> find(vector<int> &v, int k) {//find largest sequence with k elements;
  16.         vector<int> res(k);
  17.         int len = v.size();
  18.         for(int i=0, j=0; i<len; ++i) {
  19.             while(len-i+j>k && j>0 && res[j-1] < v[i]) --j;
  20.             if(j<k) res[j++] = v[i];
  21.         }
  22.         return res;
  23.     }
  24.     bool larger(vector<int> &v1, int i, vector<int> &v2, int j) {//very useful comp function
  25.         while(i<v1.size() && j<v2.size() && v1[i] == v2[j]) {
  26.             ++i;
  27.             ++j;
  28.         }
  29.         return j == v2.size() || (i < v1.size() && v1[i] > v2[j]);
  30.     }
  31.     vector<int> merge(vector<int> &v1, vector<int> &v2) {//merge two arrays into the largest one;
  32.         int m = v1.size(), n = v2.size();
  33.         vector<int> res(m+n);
  34.         for(int i=0, j=0, k = 0; i<v1.size() || j <v2.size(); ++k) {
  35.             res[k] = larger(v1, i, v2, j) ? v1[i++] : v2[j++];
  36.         }
  37.         return res;
  38.     } 
  39. };


There is another way to implement the find (vector<int>, int) function.

  1. vector<int> find(vector<int> &v, int k) {//find k elements which gives the largest value;
  2.         vector<int> res(k);
  3.         int len = v.size();
  4.         if(!k && len < k) return res;
  5.         if(len == k) return v;
  6.         int left = 0, right = len - k, i = 0;
  7.         while(i < k) {
  8.             int idMax = left;//initialization
  9.             for(int i=left; i<=right; ++i) {
  10.                 if(v[i] > v[idMax]) idMax = i;
  11.             }
  12.             res[i++] = v[idMax];
  13.             left = idMax + 1;//shift search range
  14.             ++right;
  15.         }
  16.         return res;
  17.     }

Follow-up: all the questions can be converted into finding the largest string sequence with strings.

No comments:

Post a Comment