- 题目分析:
给定两个长度分别为m和n的数组,数组元素为0-9,每个数组元素代表一个数字。从这两个数组中选出一些数字,组成一个数组,是这个数组中的数尽可能大,其长度k <= m + n。要求数组中选出的元素的相对顺序与原数组保持一致。最终返回一个包含k个数字的数组。
- 解题思路:
1)分别从nums1(长度为m)和nums2(长度为n)中挑选出i(max(0, k - n) <= i <= min(m, k) 和k-i个数,在保持挑选数组的元素相对顺序不变的情况下,使选出的子数组最大化,主要利用贪心算法进行选取;
2)在保持元素相对位置不变的前提下,将数组nums1与nums2合并,使合并的数组最大化。
- 实现程序
- C++版本
// 贪心求数组中的最大子数组 vector<int> findMaxKValue(vector<int> &nums, int k) { vector<int> result; if (k == 0) return result; result = vector<int>(k, 0); int j = 0; int n = nums.size(); for (int i = 0; i < n; i++) { // 出栈操作 while (j > 0 && n - i + j > k && nums[i] > result[j - 1]) j--; // 入栈操作 if (j < k) result[j++] = nums[i]; } return result; } // merge操作中的对比函数 bool compare(vector<int> &result1, int i, vector<int> &result2, int j) { while (i < result1.size() && j < result2.size() && result1[i] == result2[j]) { i++; j++; } return j == result2.size() || (i < result1.size() && result1[i] > result2[j]); } // 两个数组的merge操作 vector<int> merge(vector<int> &nums1, vector<int> &nums2) { int m = nums1.size(); int n = nums2.size(); if (!m) return nums2; if (!n) return nums1; vector<int> result(m + n, 0); int i = 0; int j = 0; int k = 0; // 数组合并操作 while (i < m || j < n) { result[k++] = compare(nums1, i, nums2, j) ? nums1[i++] : nums2[j++]; } return result; } // 返回两个数组中最大的k个数,并保持每个数组中的元素相对位置不变 vector<int> maxNumber(vector<int> &nums1, vector<int> &nums2, int k) { int m = nums1.size(); int n = nums2.size(); vector<int> result(k, 0); // 从数组nums中挑选k个数,在保持元素相对顺序不变的情况下,使得选出的子数组最大化。 for (int i = max(0, k - n); i <= min(m, k); i++) { // 在数组nums1中挑选i个数 vector<int> result1 = findMaxKValue(nums1, i); // 在数组nums2中挑选k-i个数 vector<int> result2 = findMaxKValue(nums2, k - i); // 将两个挑选出的子数组进行合并 vector<int> temp = merge(result1, result2); // 比较大小,来判断是否更新数组 if (compare(temp, 0, result, 0)) result = temp; } return result; }
- Java版本
private boolean compare(int[] result1, int pos1, int[] result2, int pos2) { for ( ; pos1 < result1.length && pos2 < result2.length; pos1++, pos2++){ if (result1[pos1] > result2[pos2]) return true; if (result1[pos1] < result2[pos2]) return false; } return pos1 != result1.length; } private int[] findMaxKValue(int[] nums, int k) { int[] result = new int[k]; int len = 0; for (int i = 0; i < nums.length; i++){ while (len > 0 && len + nums.length - i > k && result[len - 1] < nums[i]){ len--; } if (len < k) result[len++] = nums[i]; } return result; } public int[] maxNumber(int[] nums1, int[] nums2, int k){ int[] result = new int[k]; for (int i = Math.max(k - nums2.length, 0); i <= Math.min(nums1.length, k); i++){ int[] result1 = findMaxKValue(nums1, i); int[] result2 = findMaxKValue(nums2, k - i); // 对两个数组执行merge操作 int[] temp = new int[k]; int pos1 = 0; int pos2 = 0; int tpos = 0; while (pos1 < result1.length || pos2 < result2.length){ temp[tpos++] = compare(result1, pos1, result2, pos2) ? result1[pos1++] : result2[pos2++]; } if (!compare(result, 0, temp, 0)) result = temp; } return result; }
- C++版本
- 参考文献
http://bookshadow.com/weblog/2015/12/24/leetcode-create-maximum-number/
时间: 2024-10-16 15:10:09