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

让天下没有难学的算法

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

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

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

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

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

文章目录

  • 一、题目
    • 1、题目描述
    • 2、基础框架
    • 3、原题链接
  • 二、解题报告
    • 1、思路分析
    • 2、时间复杂度
    • 3、代码详解
  • 三、本题小知识

一、题目

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);

三、本题小知识

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


你可能感兴趣的:(《LeetCode算法全集》,算法,leetcode,数据结构,二分枚举,枚举)