问题描述:
两个数组 a 和 b,询问 b 的哪一段连续子数组之和与数组 a 之和最接近。
如果有多个子数组之和同样接近,输出起始点最靠左的数组。
输入描述:
第一行输入两个正整数 n 和 m ,表示数组 a 和 b 的长度。
第二第三行输入 n 个和 m 个正整数,表示数组中 a 和 b 的值。
输出描述:
输出子数组之和最接近 a 的子数组。
示例:
输入:
2 6
30 29
15 29 42 1 44 1
输出:
29 42
问题分析:
要想找出最接近a数组的子数组,我们应该要设计两个指针,一个指向b数组中的第一个元素,一个
则指向第二个元素,同时定义一个min来定义a数组和和b数组的子数组的差值,相当于通过增加子
数组中的元素来增大子数组的值。
接下来就是实现:
1.输入m,n以及两个数组并计算数组a的和:
int arr1[50] = { 0 };
int arr2[50] = { 0 };
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int i = 0;
int j = 0;
int sum1 = 0;
for (i = 0; i < m; i++)
{
scanf("%d", &arr1[i]);
sum1 += arr1[i];
}
for (j = 0; j < n; j++)
{
scanf("%d", &arr2[j]);
}
2.写入一个循环来比较子数组与a数组的大小:
while (left < right && right < n)
{
sum2 = 0;
for (int a = left; a <= right; a++)
{
sum2 += arr2[a];
}
if (abs(sum2 - sum1) < min)
{
min = abs(sum2 - sum1);
cl = left;
cr = right;
}
if (sum2 > sum1)
{
left++;
}
if (sum2 < sum1)
{
right++;
}
}
(1)计算子数组的和
for (int a = left; a <= right; a++)
{
sum2 += arr2[a];
}
(2)找到最接近a数组的子数组:
if (abs(sum2 - sum1) < min)
{
min = abs(sum2 - sum1);
cl = left;
cr = right;
}
(3)如果子数组大于a数组减少子数组元素:
if (sum2 > sum1)
{
left++;
}
(4)如果子数组小于a数组增加子数组元素:
if (sum2 < sum1)
{
right++;
}
所有代码:
#include<math.h>
int main()
{
int arr1[50] = { 0 };
int arr2[50] = { 0 };
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int i = 0;
int j = 0;
int sum1 = 0;
for (i = 0; i < m; i++)
{
scanf("%d", &arr1[i]);
sum1 += arr1[i];
}
for (j = 0; j < n; j++)
{
scanf("%d", &arr2[j]);
}
int left = 0;
int right = 1;
int min = sum1;
int cl = 0;
int cr = 0;
int sum2 = 0;
if (n == 1)
{
printf("%d", arr2[0]);
return 0;
}
while (left < right && right < n)
{
sum2 = 0;
for (int a = left; a <= right; a++)
{
sum2 += arr2[a];
}
if (abs(sum2 - sum1) < min)
{
min = abs(sum2 - sum1);
cl = left;
cr = right;
}
if (sum2 > sum1)
{
left++;
}
if (sum2 < sum1)
{
right++;
}
}
for (i = cl; i <= cr; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
接下来我们看一下每次循环的示意图:
1.
2.
3.
4.
5.
6.
7.
8.