1083-是否存在相等的差(PAT-B)

20 篇文章 0 订阅

题目如下:

给定 N 张卡片,正面分别写上 1、2、……、N,然后全部翻面,洗牌,在背面分别写上 1、2、……、N。将每张牌的正反两面数字相减(大减小),得到 N 个非负差值,其中是否存在相等的差?
输入格式:

输入第一行给出一个正整数 N(2 ≤ N ≤ 10 000),随后一行给出 1 到 N 的一个洗牌后的排列,第 i 个数表示正面写了 i 的那张卡片背面的数字。
输出格式:

按照“差值 重复次数”的格式从大到小输出重复的差值及其重复的次数,每行输出一个结果。
输入样例:

8
3 5 8 6 2 1 4 7
输出样例:

5 2
3 3
2 2

解决方案:

1.思路:读题:题意为正面的数字分别是1、2、…、N,接着输入洗牌后的数字,拿输入的数字按顺序和正面的数字1、2、3、…、N做减法,看是否有相等的差
用输入样例来举例:

正面数字:1  2  3  4  5  6  7  8
输入数字:3  5  8  6  2  1  4  7
做差以后:2  3  5  2  3  5  3  1

可以看出,差值为2的有两个,差值为三的有3个,差值为5的有两个,然后按照题目要求输出即可。
明白题意后,使用一个差值数组来保存这些差值,然后将这些差值排序,遍历差值数组,如果当前元素的后一个和当前元素不同,而且当前元素出现了不止一次,就可以将当前元素输出。当然,还需要一个变量来记录当前元素的次数。
按照以上思路第一次写代码的时候,却出现了问题,并没有成功通过,下方为有问题的代码:

//将差值放入数组
for(int i = 0; i < N; i++) {
		cin >> num;
		if(num > i) sub[i] = num - 1 - i;  //数比下标大 
		else sub[i] = i - num + 1;  //数字比下标小  i-(num-1)
	}
//对差值数组排序
sort(sub, sub + N, cmp);
//遍历数组找不同
for(int i = 0; i < N; i++) {
		times++;  //从第一个元素开始累积次数,如果达到要求,就将次数归零,然后重新累加
		//当时想的是如果重复次数超过1次,而且和后一个元素不同,就输出,然后将times归零
		if(sub[i + 1] != sub[i] && times > 1) { 
			cout << sub[i] << " " << times << endl;
			times = 0;
		}
	}

可是提交的时候却没有通过,有两个测试点是错误的,看了半天并没有发现什么问题,于是只好亲自动手写了几个数据来测试,终于发现了问题:

10
1  7  5  6  8  4  1  6  9  3
洗牌的数字是:1  7  5  6  8  4  1  6  9  3
正面的数字是:1  2  3  4  5  6  7  8  9  10
差值:       0  5  2  2  3  2  6  2  0  7

排序后的数组第一个元素和第二个元素分别是7和6,这时候问题产生了,7和6不同,执行到第二个元素6的时候,按照正常想法应该是times归0,然后继续执行下一个元素;可是代码却在这里输出了6。这是因为判断条件写成了“且”条件,需要同时满足前后元素不同和times > 1两个条件,可是在执行第一个元素7的时候,虽然前后元素不同,可是times只加了1,此时times只是1,并不是2,因此没有输出,同时也没有归0。解决方法是将归0条件从times > 1中提取出来,这样的话前后元素只要出现不同,就将times归0。修正后的代码为:

for(int i = 0; i < N; i++) {
		times++;
		if(sub[i + 1] != sub[i]) {
			if(times > 1)  cout << sub[i] << " " << times << endl;
			times = 0;
		}
	}

完整代码:

#include <iostream>
#include <algorithm> 
using namespace std;
bool cmp(int a, int b) 
{
	return a > b;
}
int main()
{
	int N;
	int num;
	int times = 0;
	cin >> N; 
	int sub[N + 1]; 
	for(int i = 0; i < N; i++) {
		cin >> num;
		if(num > i) sub[i] = num - 1 - i;  
		else sub[i] = i - num + 1;  
	}
	sort(sub, sub + N, cmp);
	for(int i = 0; i < N; i++) {
		times++;
		if(sub[i + 1] != sub[i]) {
			if(times > 1)  cout << sub[i] << " " << times << endl;
			times = 0;
		}
	}
}

大神的解答:

柳神的方法是:将差值作为数组的下标,一旦产生一个差值,就将对应的元素的值+1,最后遍历数组,将元素值大于2的输出。比如产生差值为3,就把数组第四个元素a[3]加一,最后输出下标3和对应的元素值。
柳神的解析:PAT 1083. 是否存在相等的差 (20) - 乙级
附柳神的代码:

#include <iostream>
using namespace std;
int main() {
    int n, t, a[10000] = {0};
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> t;
        a[abs(t-i)]++;
    }
    for (int i = 9999; i >= 0; i--)
        if (a[i] >= 2) cout << i << " " << a[i] << endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值