求解满足条件的元素对个数问题(分治算法—课程设计)

问题描述

给定N个整数A[i]以及一个正整数C,问其中有多少对i,j满足A[i]-A[j]=C。

输入描述

第1行输入两个空格隔开的整数N和C,第2~N+1行每行包含一个整数A[i].
在这里插入图片描述

输出一个数表示答案

在这里插入图片描述

主要算法思想

此设计中主要采用了分治算法的一些思想

分治算法的主要思想

当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。

使用分治算法的基本步骤

step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
step3 合并:将各个子问题的解合并为原问题的解。

分治算法的应用条件

1.问题的规模缩小到一定程度就可以容易地解决。
2.问题具有最优子结构性质(当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质)
3.分解出的子问题的解可以合并为该问题的解。
4.问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

在这个问题中分治算法的具体应用

首先采用二分查找数量。先对数组a递增排序,用j扫描数组a,对于元素a[j],在a[j+1…n-1]中采用二分法求元素a[j]+c出现的次数count(不存在时count=0),累计所有的count得到ans即为所求。其中在有序序列中查找a[j]+c元素出现次数的二分发就是分治思路。

详细设计

search函数模块(分治算法模块)
int search(int low,int high,int x)
{
			while(low<=high)
		{
			int mid = (low+high)/2;
			if(a[mid]==x)
			{
				int count=1,i;
				i=mid-1;
				while(i>=low&&a[i]==x)
				{
					count++;
					i--;
				}
				i=mid+1;
				while(i<=high&&a[i]==x)
				{
					count++;
					i++;
				}
				return count;
				}
				else if(x>a[mid])
					low=mid+1;
				else
		 			high=mid-1;
				}
				return 0;
}
主函数模块
int main(){
	scanf("%d%d",&n,&c);
	for(int i=0;i<n;i++)
	scanf("%d",&a[i]);
	sort(a,a+n);
	int ans = 0;
	for(int j=0;j<n-1;j++)
	  ans+=search(j+1,n-1,a[j]+c);
	  printf("A[i]-A[j]=c出现的次数为%d\n",ans);
	  return 0;}

流程图

主函数模块流程图

在这里插入图片描述

search函数模块流程图(算法模块)

在这里插入图片描述

详细代码

#include<stdio.h>
#include<algorithm>
using namespace std;
#define MAXN 200000
int a[MAXN];
int n,c;
int search(int low,int high,int x)
{
	while(low<=high)
	{
		int mid = (low+high)/2;
		if(a[mid]==x)
		{
			int count=1,i;
			i=mid-1;
			while(i>=low&&a[i]==x)
			{
				count++;
				i--;
			}
			i=mid+1;
			while(i<=high&&a[i]==x)
			{
				count++;
				i++;
			}
			return count;
		}
		else if(x>a[mid])
		low=mid+1;
		else
		 high=mid-1;
	}
	return 0;
}
int main()
{
	scanf("%d%d",&n,&c);
	for(int i=0;i<n;i++)
	scanf("%d",&a[i]);
	sort(a,a+n);
	int ans = 0;
	for(int j=0;j<n-1;j++)
	  ans+=search(j+1,n-1,a[j]+c);
	  printf("A[i]-A[j]=c出现的次数为%d\n",ans);
	  return 0;
}
  • 11
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值