列表

详情


BC156. 牛牛的数组匹配

描述

牛牛刚学会数组不久,他拿到两个数组 a 和 b,询问 b 的哪一段连续子数组之和与数组 a 之和最接近。
如果有多个子数组之和同样接近,输出起始点最靠左的数组。

输入描述

第一行输入两个正整数 n 和 m ,表示数组 a 和 b 的长度。
第二第三行输入 n 个和 m 个正整数,表示数组中 a 和 b 的值。

输出描述

输出子数组之和最接近 a 的子数组

示例1

输入:

2 6
30 39 
15 29 42 1 44 1

输出:

29 42

示例2

输入:

6 1
50 47 24 19 46 47 
2

输出:

2

原站题解

C 解法, 执行用时: 2ms, 内存消耗: 292KB, 提交时间: 2022-03-13

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
    int arr1[100] = { 0 };
    int arr2[100] = { 0 };
    int a, b;
    int x, y;
    scanf("%d%d", &a, &b);
    int sum1 = 0;
    int sum2 = 0;
    int i = 0;
    for (i = 0;i < a;i++) {
        scanf("%d", &arr1[i]);
        sum1 += arr1[i];
    }
    for (i = 0;i < b;i++) {
        scanf("%d", &arr2[i]);
        sum2 += arr2[i];
    }
    int min = 1000000;
    //这里少了一个遍历
  for (i = 0;i < b - 1;i++)
    {
        int m = i;
        int summ = 0;
        int j = 0;
        for (j = i + 1;j < b;j++)
        {
            while (m <= j) {
                summ += arr2[m];
                m++;
            }
            if (min > abs(summ - sum1)) {
                //找到了
                min = abs(summ - sum1);
                x = i;
                y = j;
            }
            m = i;
            summ = 0;
        }
    }
    if (b == 1) {
        printf("%d", arr2[0]);
    }
    else {
        for (i = x;i <= y;i++) {
            printf("%d ", arr2[i]);
        }
    }
    return 0;
}

C 解法, 执行用时: 2ms, 内存消耗: 296KB, 提交时间: 2022-06-16

#include <stdio.h>
#include <math.h>

int* compute(int arr2[], int m, int i, int sum1, int sum2){
    int arr[2]; //存放两个参数 找到本轮最优解时候的sum 和 j
    int sub = 0;    
    for(int n = 0; n < i; n++)
            sum2 -= arr2[n]; //本轮初始值
    for(int j = m - 1; j >= i; j--){
        if(abs(sum2 - arr2[j] - sum1) < abs(sum2 - sum1)) //比较差值
            sum2 -= arr2[j];
        else{
            arr[0] = sum2; //当轮最优解元素和
            arr[1] = j;    //当轮最优解尾元素下标
            break;
        } 
    }
    return arr;
}
/*思路:从完整数组开始,不断去掉前面的一个元素,用剩下的子数组进行下轮比较;
*每轮判断规则(如果满足减去数组2当前的最后一个元素后,如果和数组1差值变小了,
*就继续减去尾元素,直到满足差值最小,得到本轮最优解; 用该值和下一轮进行比较,
*如果下一轮差值更小,则继续切割数组,找更下一轮,直到不满足,然后根据i,j位置输出数组元素;  
*/
int main(){
    int n, m, arr1[10], arr2[10], sum1 = 0, sum2 = 0;
    int res;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        scanf("%d", &arr1[i]);
        sum1 += arr1[i];
    }
    for(int j = 0; j < m; j++){
        scanf("%d", &arr2[j]);
        sum2 += arr2[j];
    }
    int min = *(compute(arr2, m, 0, sum1, sum2));
    for(int i = 1; i < m; i++){
        res = *compute(arr2, m, i, sum1, sum2);
        if(abs(res - sum1) < abs(min - sum1)) //比较差值
			min = res;	
        else{
        	i--; //不满足要回溯 
            int j = *(compute(arr2, m, i, sum1, sum2) + 1);
            for(int s = i; s <= j; s++)
                printf("%d ", arr2[s]);
            break;
        }
    }
    return 0;
}

C 解法, 执行用时: 2ms, 内存消耗: 296KB, 提交时间: 2022-03-27

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void FindMin(int* left, int* right, int* b, int m, int sum)
{
    int difference = 0xffff;
    int i, j;
    for (i = 0; i < m; i++)
    {
        int tem = -sum;
        for (j = i; j < m; j++)
        {
            tem += b[j];
            if (tem > 0)
            {
                if (abs(tem) < abs(tem - b[j]))
                {
                    if (abs(tem) < difference)
                    {
                        difference = abs(tem);
                        *left = i;
                        *right = j;
                    }
                }
                if (abs(tem) > abs(tem - b[j]))
                {
                    if (abs(tem - b[j]) < difference)
                    {
                        difference = abs(tem - b[j]);
                        *left = i;
                        *right = j - 1;
                    }
                }
            }
        }
    }
}
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    int* a = (int*)malloc(sizeof(int) * n);
    int* b = (int*)malloc(sizeof(int) * m);
    int i = 0, j = 0;
    int sum = 0,sumb=0;
        for (i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
            sum += a[i];
        }
    for (i = 0; i < m; i++)
    {
        scanf("%d", &b[i]);
        sumb+=b[i];
    }
    if(sumb<sum)
    {
        for(i=0;i<m;i++)
        {
            printf("%d ",b[i]);
        }
    }
    else
    {
    int left = 0, right = 0;
    FindMin(&left, &right, b, m, sum);
    for (i = left; i <= right; i++)
    {
        printf("%d ", b[i]);
    }
    }
    free(a), free(b);
    a = NULL, b = NULL;
    return 0;
}

C 解法, 执行用时: 2ms, 内存消耗: 304KB, 提交时间: 2022-03-11

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int Differ(int *left, int *right,int *p,int n,int d,int sum )
{
    int and=0;
    int difference=0xffff;
    for(int i=0;i<n-d+1;i++)
    {
        and=0;
        for(int j=0;j<d;j++)
        {
           and+=p[i+j];
        }
        if(difference>abs(and-sum))
            difference=abs(and-sum),*left=i,*right=i+d-1;
    }
    return  difference;
}
int main()
{
    int n=0,m=0,sum=0,sumb=0;
    scanf("%d %d",&n,&m);
    int *a=(int*)malloc(n*sizeof(int));
    int *b=(int*)malloc(m*sizeof(int));
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    getchar();
    for(int i=0;i<m;i++)
        scanf("%d",&b[i]);
    int left=0,right=0;
    int sum_left=0,sum_right=0;
    int difference=0xffff,sum_difference=0xffff;
    for(int i=0;i<m;i++)
    {
        sum_difference=Differ(&sum_left,&sum_right,b,m,i+1,sum);
        if((sum_difference<difference)||((sum_difference==difference)&&(sum_left<left)))
            left=sum_left,right=sum_right,difference=sum_difference;
    }
    for(int i=left;i<(right+1);i++)
    printf("%d ",b[i]);
}

C 解法, 执行用时: 2ms, 内存消耗: 312KB, 提交时间: 2022-05-08

#include<stdio.h>
int main()
{
    int i, j, t, n, m, sum = 0, flag = 9999, temp = 0, l = 0, r = 0;
    scanf("%d %d", &n, &m);//数组a,b的长度
  //  getchar();
    int b[100] = { 0 };
    for (i = 0; i < n; i++) {
        scanf("%d",&j);
        sum += j;
    }//sum是数组a各元素之和
   // getchar();
    for (i = 0; i < m; i++) {
        scanf("%d", &b[i]);
    }//存入数组b
    for (j = 0; j < m; j++) {//数组中第j个数
        temp = 0;
        for (i = j; i < m; i++) {//第j个数和它后面的所有数
            temp += b[i]; 
            if (temp == sum) {//子数组之和恰好等于数组a的和,输出子数组
                for ( t = j; t <= i; t++) 
                return 0;
            }
            else if (temp > sum) {//子数组之和大于数组a的和,且子数组更接近数组a
                if (temp - sum < flag) { l = j; r = i; flag = temp - sum; }//记录此子数组的开始点和结束点
            }
            else {//同上
                if (sum - temp < flag) { l = j; r = i; flag = sum - temp; }
            }
        }
    }
    for ( t = l; t <= r; t++) 
    { 
        printf("%d ", b[t]);
    }
}

上一题