差 解题报告
D e s c r i p t i o n \rm Description Description
描述
楠楠在网上刷题,感觉第一题:求两数的和 ( ( ( A + B A+B A+B P r o b l e m Problem Problem ) ) ) 太无聊了,于是增加了一题: ( ( ( A − B A-B A−B P r o b l e m Problem Problem ) ) ),难倒了一群小朋友,哈哈。
题目是这样的:给出N个从小到大排好序的整数,一个差值C,要求在这N个整数中找两个数A和B,使得A-B=C,问这样的方案有多少种?
例如: N = 5 N=5 N=5, C = 2 C=2 C=2, 5 5 5 个整数是: 2 2 2 2 2 2 4 4 4 8 8 8 10 10 10 。答案是 3 3 3 。具体方案:第 3 3 3 个数减第 1 1 1 个数;第 3 3 3 个数减第 2 2 2 个数;第 5 5 5 个数减第 4 4 4 个数。
输入
第一行 2 2 2 个正整数: N , C N,C N,C 。第二行 N N N 个整数:已经有序。注意:可能有相同的。
输出
一个整数,表示该串数中包含的所有满足 A − B = C A-B=C A−B=C 的数对的方案数。
输入样例
4 1
1 1 2 2
输出样例
4
提示
【数据范围】:
5 5 5 个数据: N \rm N N 的范围是 [ 1 … 1 , 000 ] [1…1,000] [1…1,000]。
5 5 5 个数据: N \rm N N 的范围是 [ 1 … 100 , 000 ] [1…100,000] [1…100,000]。
【所有数据】:
C的范围是 [ 1 … 1 , 000 , 000 , 000 ] [1…1,000,000,000] [1…1,000,000,000]。
N个整数中每个数的范围是: [ 0 … 1 , 000 , 000 , 000 ] [0…1,000,000,000] [0…1,000,000,000]。
解题部分
思路一
首先,我们找的应该是
A
−
B
=
C
A-B=C
A−B=C ,由小学数学得我们可以知道可以找
B
+
C
=
A
B+C=A
B+C=A ,所以可以直接暴力枚举
B
B
B 和
C
C
C 。
时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
思路二(原始思路)
可以直接枚举每一个点,然后再将它左边的点一个一个减,当差大于时停止,换下一个点枚举。
时间复杂度约为
O
(
n
2
)
O(n^2)
O(n2)
思路三(原始思路改良版)
也是枚举每一个点,例如当前的点为B,用二分答案找到等于A的最左边的坐标,再用二分答案找到小于A的点的坐标,两个相减得到一共有多少个A,然后累加起来,最后输出。
时间复杂度为约为
O
(
n
2
l
o
g
n
)
O(n2logn)
O(n2logn)
for(int i=1; i<=n; i++)//枚举每个数
{
int l=1, r=n;
num=a[i]+c;//B+C=A,a[i]是B
while(l<=r)
{
int mid=(l+r) >> 1;
if(a[mid]<num) l=mid+1;
else r=mid-1;
}
//找到小于A的点的坐标
ans1=l;
l=1,r=n;//记得要初始化!
while(l<=r)
{
int mid=(l+r) >> 1;
if(a[mid]<=num) l=mid+1;
else r=mid-1;
}//找到等于A的点的坐标
ans2=l;
ans+=ans2-ans1;
}
这篇解题报告详细介绍了如何解决‘A-B Problem’,即在已排序的整数序列中寻找满足A-B=C的数对方案数。讨论了三种思路,包括暴力枚举、原思路优化及二分查找方法,探讨了它们的时间复杂度,并提供了输入输出样例及数据范围。

1029

被折叠的 条评论
为什么被折叠?



