XTU-OJ 《C语言程序设计》 1054-平方数

文章提供了一个关于寻找整数集合中满足y=x*x条件的数对的问题。初始的暴力求解方法是通过两层循环遍历,但考虑到效率,作者提出了使用快速排序对数组进行排序,然后通过二分查找来优化搜索过程,尤其是当元素可能达到100000000时,避免平方导致的int溢出。这种方法结合了排序和查找算法,提高了效率。
摘要由CSDN通过智能技术生成

描述

       给你一个整数集合A(无重复元素),如果x,y都属于A,且y=x*x,那么组成一个数对,请找出这个集合中满足条件的数对的个数。比如说集合A={2,3,4},则只有4=2*2,则答案为1。

输入

       每个样例占2行,第一行为一个非负整数n,n<=1000,为集合中元素的个数,如果n为0则输入结束。第二行为n个整数,为集合的元素,所有的元素为非负整数,且<=100,000,000,两个整数之间有一个空格隔开。

输出

       每行输出一个样例的结果。

Sample Input

3
2 3 4
5
3 36 5 9 6
0

Sample Output

1
2

如果我们采用简单的暴力求解的话,这题是非常简单的,两个for循环遍历就能AC,仅仅需要注意元素最大值可为 100000000,如果再平方的话会爆int,所以要用 long long 类型的数组保存。

暴力AC代码如下:

#include <stdio.h>

int main()
{
	long long num[1010];
	int n,cnt;
    while ( scanf("%d",&n) !=  EOF  && n != 0)
    {
        cnt = 0;
        for (int i = 0; i < n; i ++)
            scanf("%lld",&num[i]);
		for (int i = 0; i < n; i ++)
			for (int j = 0; j < n; j ++)
				if (num[i]*num[i] == num[j])
					cnt ++;
		printf("%d\n",cnt);
	}
	return 0;
}

但在这一题上是否还能再拓展一下呢。尝试用别的方法解题。作者这里写了一份利用二分查找来判断是否存在一个数对的代码。写的代码可能是比暴力的更加繁琐,但也算用到了更多知识。

这里我们用到了 快速排序,二分查找,位运算的知识,大家有兴趣的可以去学习了解下哦。

有人不懂 第18行 为什么是 num[i] <= 1e4。因为集合中的元素最大是 100000000。如果 大于10000的元素,是一定找不到它的平方数的。(我们已经通过快速排序,将num数组中的元素,按从小到大的顺序排好序了)

#include <stdio.h>
#include <stdlib.h>

int cmp(const void *a,const void *b) {
	return *(int*)a - *(int*)b;
}

int main()
{
    int n,cnt;
    int num[1010];
    while ( scanf("%d",&n) !=  EOF  && n != 0)
    {
        cnt = 0;
        for (int i = 0; i < n; i ++)
            scanf("%d",&num[i]);
        qsort(num,n,sizeof(int),cmp);      //  qsort() 快速排序函数
        for (int i = 0; num[i] <= 1e4; i ++)
        {
            int left = 0,right = n-1;       // 二分查找
            int mid,y;
            y = num[i]*num[i];   
            while (left <= right)
            {
                mid = (left + right) >> 1;    //  位运算,  >> 1 表示左移一位,就相当于 除2
                if (y > num[mid])
                    left = mid+1;
                else if (y < num[mid])
                    right = mid-1;
                else
                {
                    cnt ++;
                    break;
                }
            } 
        }
        printf("%d\n",cnt);
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值