You are given two integer arrays nums1 and nums2 both of the same length. The advantage of nums1 with respect to nums2 is the number of indices i for which nums1[i] > nums2[i].
Return any permutation of nums1 that maximizes its advantage with respect to nums2.
Example 1
Input: nums1 = [2,7,11,15], nums2 = [1,10,4,11]
Output: [2,11,7,15]
Example 2
Input: nums1 = [12,24,8,32], nums2 = [13,25,32,11]
Output: [24,32,8,12]
Constraints
- 1 <= nums1.length <= 10e5
- nums2.length == nums1.length
- 0 <= nums1[i], nums2[i] <= 10e9
Soution
一个超时的朴素田忌赛马:比较 nums1 和 nums2 的最小元素,nums1 大就对应;nums1 小就拿去和 nums2 最大的对应。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int findMax(int* nums, int numsSize){
int i, max;
for (i = 0; i < numsSize; i++) {
if (nums[i] != -1) {
max = i;
break;
}
}
for (i = 0; i < numsSize; i++)
if (nums[i] != -1 && nums[i] > nums[max]) max = i;
return max;
}
int findMin(int* nums, int numsSize){
int i, min;
for (i = 0; i < numsSize; i++) {
if (nums[i] != -1) {
min = i;
break;
}
}
for (i = 0; i < numsSize; i++)
if (nums[i] != -1 && nums[i] < nums[min]) min = i;
return min;
}
int* advantageCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int i, n, mina, minb, maxa, maxb;
n = nums1Size;
int *ans = (int*)malloc(sizeof(int) * n);
int *a = (int*)malloc(sizeof(int) * n);
int *b = (int*)malloc(sizeof(int) * n);
for (i = 0; i < n; i++) {
a[i] = nums1[i];
b[i] = nums2[i];
}
for (i = 0; i < n; i++) {
mina = findMin(a, n);
minb = findMin(b, n);
if (a[mina] > b[minb]) {
ans[minb] = a[mina];
a[mina] = -1;
b[minb] = -1;
} else {
maxb = findMax(b, n);
ans[maxb] = a[mina];
a[mina] = -1;
b[maxb] = -1;
}
}
*returnSize = n;
return ans;
}
先快速排序后的优化算法:
思路与算法
我们首先分别将数组 nums1 和 num2 进行排序,随后只需要不断考虑这两个数组的首个元素:
-
如果 nums 1 的首个元素大于 nums2 的首个元素,那么就将它们在答案中对应起来,同时从数组中移除这两个元素,并增加一点「优势」;
-
如果 nums1 的首个元素小于等于 nums2 的首个元素,那么移除 nums1 的首个元素。
当 nums1 中没有元素时,遍历结束。
这样做的正确性在于:
-
对于第一种情况,由于 nums1 是有序的,那么 nums1的任意元素大于 nums2 的首个元素:
- 如果我们不与 nums2 的首个元素配对,由于 nums2 是有序的,之后的元素会更大,这样并不划算;
- 如果我们与 nums2 的首个元素配对,我们使用 nums1 的首个元素,可以使得剩余的元素尽可能大,之后可以获得更多「优势」。
-
对于第二种情况,由于 nums2 是有序的,那么 nums1 的首个元素小于等于 nums2 中的任意元素,因此 nums1 的首个元素无法增加任何「优势」,可以直接移除。
在本题中,由于 num1 中的每一个元素都要与 nums2 中的元素配对,而我们是按照顺序考虑 nums2 中的元素的。因此在遍历结束后,nums2 中剩余的元素实际上是原先 nums2 的一个后缀。因此当 nums1 的首个元素无法配对时,我们给它配对一个 nums2 的尾元素即可,并将该尾元素移除。
在实际的代码编写中,我们无需真正地「移除」元素。对于 nums1,我们使用一个循环依次遍历其中的每个元素;对于 nums2 ,我们可以使用双指针 left 和 right 。如果 nums1 的首个元素可以增加「优势」,就配对 left 对应的元素并向右移动一个位置;如果无法配对,就配对 right 对应的元素并向左移动一个位置。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
static int cmp(const void *pa, const void *pb){
int *a = (int *)pa;
int *b = (int *)pb;
return a[1] - b[1];
}//nondecending order
int* advantageCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int i, n, left, right;
n = nums1Size;
int *ans = (int*)malloc(sizeof(int) * n);
int a[n][2], b[n][2];
for (i = 0; i < n; i++) {
a[i][0] = i; a[i][1] = nums1[i];
b[i][0] = i; b[i][1] = nums2[i];
}
qsort(a, n, sizeof(a[0]), cmp);
qsort(b, n, sizeof(b[0]), cmp);
left = 0; right = n - 1;
for (i = 0; i < n; i++) {
if (a[i][1] > b[left][1]) {
ans[b[left][0]] = a[i][1];
left++;
} else {
ans[b[right][0]] = a[i][1];
right--;
}
}
*returnSize = n;
return ans;
}
动态分配内存的方法注意 cmp 函数的写法。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int cmp(const void *pa, const void *pb){
int *a = *(int **)pa;
int *b = *(int **)pb;
return a[1] - b[1];
}//nondecending order
int* advantageCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int i, n, left, right;
n = nums1Size;
int *ans = (int*)malloc(sizeof(int) * n);
int **a = (int**)malloc(sizeof(int*) * n);
int **b = (int**)malloc(sizeof(int*) * n);
for (i = 0; i < n; i++) {
a[i] = (int*)malloc(sizeof(int) * 2);
b[i] = (int*)malloc(sizeof(int) * 2);
a[i][0] = i; a[i][1] = nums1[i];
b[i][0] = i; b[i][1] = nums2[i];
}
qsort(a, n, sizeof(a[0]), cmp);
qsort(b, n, sizeof(b[0]), cmp);
left = 0; right = n - 1;
for (i = 0; i < n; i++) {
if (a[i][1] > b[left][1]) {
ans[b[left][0]] = a[i][1];
left++;
} else {
ans[b[right][0]] = a[i][1];
right--;
}
}
for (i = 0; i < n; i++) {
free(a[i]);
free(b[i]);
}
free(a);
free(b);
*returnSize = n;
return ans;
}