⭐算法入门⭐《二分枚举》中等01 —— LeetCode 面试题 16.21. 交换和

🔥让天下没有难学的算法🔥

C语言免费动漫教程,和我一起打卡!
🌞《光天化日学C语言》🌞

入门级C语言真题汇总
🧡《C语言入门100例》🧡

几张动图学会一种数据结构
🌳《画解数据结构》🌳

组团学习,抱团生长
🌌《算法入门指引》🌌

竞赛选手金典图文教程
💜《夜深人静写算法》💜

一、题目

1、题目描述

  给定两个整数数组,请交换一对数值(每个数组中取一个数值),使得两个数组所有元素的和相等。返回一个数组,第一个元素是第一个数组中要交换的元素,第二个元素是第二个数组中要交换的元素。若有多个答案,返回任意一个均可。若无满足条件的数值,返回空数组。
  样例输入: array1 = [4, 1, 2, 1, 1, 2], array2 = [3, 6, 3, 3]
  样例输出: [1, 3]

2、基础框架

  • C语言 版本给出的基础框架代码如下:
int* findSwapValues(int* array1, int array1Size, int* array2, int array2Size, int* returnSize){
}

3、原题链接

LeetCode 面试题 16.21. 交换和

二、解题报告

1、思路分析

  1)首先,对第一个数组进行不降排序,然后对所有数求和为 s u m 1 sum1 sum1,那么第一个数组可以选择的数就是 x x x s u m 1 − x sum1-x sum1x
  2)然后,对第二个数组进行不降排序,然后对所有数求和为 s u m 2 sum2 sum2,那么第二个数组可以选择的数就是 y y y s u m 2 − y sum2-y sum2y;
  3)现在要达到的目的就是 x + s u m 2 − y = y + s u m 1 − x x+sum2-y = y+sum1-x x+sum2y=y+sum1x化简以后得到: 2 x = 2 y + s u m 1 − s u m 2 2x = 2y + sum1-sum2 2x=2y+sum1sum2
  4)枚举 x x x, 得到 y = ( 2 x − s u m 1 + s u m 2 ) / 2 y = (2x-sum1+sum2)/2 y=(2xsum1+sum2)/2 去数组2里查找是否存在这个 y y y 就完事了;

2、时间复杂度

  • 二分枚举答案,时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)

3、代码详解

int cmp(const void *a, const void *b) {
    return *(int *)a - *(int *)b;
}

int search(int* nums, int numsSize, int target){
    int l = 0, r = numsSize - 1;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(target == nums[mid]) {
            return mid;
        }else if(target > nums[mid]) {
            l = mid + 1;
        }else {
            r = mid - 1;
        }
    }
    return -1;
}

int* findSwapValues(int* array1, int array1Size, int* array2, int array2Size, int* returnSize){
    int i, x, y, sum1 = 0, sum2 = 0;
    int *ret = NULL;
    qsort(array1, array1Size, sizeof(int), cmp);       // (1) 
    qsort(array2, array2Size, sizeof(int), cmp);       // (2) 
    for(i = 0; i < array1Size; ++i) {
        sum1 += array1[i];                             // (3) 
    }
    for(i = 0; i < array2Size; ++i) {
        sum2 += array2[i];                             // (4) 
    }
    for(i = 0; i < array1Size; ++i) {
        x = array1[i];
        y = 2*x - sum1 + sum2;
        if(y & 1) {
            continue;                                  // (5) 
        }
        y >>= 1;                                       // (6) 
        if( search(array2, array2Size, y ) != -1) {
            ret = (int *)malloc(2 * sizeof(int));      // (7) 
            ret[0] = x;
            ret[1] = y;
            *returnSize = 2;
            return ret;
        }
    }
    *returnSize = 0;
    return NULL;
}
  • ( 1 ) (1) (1) 对第一个数组进行递增排序;
  • ( 2 ) (2) (2) 对第二个数组进行递增排序;
  • ( 3 ) (3) (3) 对第一个数组求和;
  • ( 4 ) (4) (4) 对第一个数组求和;
  • ( 5 ) (5) (5) 2 ∗ x − s u m 1 + s u m 2 2*x - sum1 + sum2 2xsum1+sum2 必须被 2 2 2 整除;
  • ( 6 ) (6) (6) 根据 x x x 计算 y y y;
  • ( 7 ) (7) (7) 返回 ( x , y ) (x, y) (x,y);

三、本题小知识

  二分的问题,可以先把问题简单分析下,列出算式,逐渐抽象,抽丝剥茧,最后抽象成二分枚举问题求解。


  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄哪里出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值