bigpotato

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Given a positive integer num, write a function which returns True if num is a perfect square else False.

Note: Do not use any built-in library function such as sqrt.

Example 1:

Input: 16
Returns: True

Example 2:

Input: 14
Returns: False

给定一个正数,判断其是否是完全平方数,要求不用sqrt。

这道题比较简单,问题是效率。

法一:从1枚举到num/2,虽然肯定是正确的,但是效率太低了通不过。

代码如下:

bool isPerfectSquare(int num)
{
	if (num == 1)
		return true;
	for (int i = 0; i <= num / 2; i++)
	{
		int tmp = i*i;
		if (tmp == num)
			return true;
		if (tmp > num)
			break;
	}
	return false;
}  

法二:法一效率低是因为枚举的范围太广了,输入num很小时还好,num很大时,比如INT_MAX时,简直是灾难!可考虑如何缩小这个范围。对于[1,num]之间的任一个数k1,若k12>num,显示[k1,num]之间的数的平方都会大于num,不需考虑;若k22<num,显然[1,k2]之间的数的平方都会小于num,也不需要考虑。若num是完全平方数,其根必然处于(k1,k2)这个区间。如果能快速确定这个区间,并使这个区间的范围尽可能小,执行效率就能明显得到改善。在此我们可以考虑首先取num的一半,即k=num/2,若k2>num,则k缩小一倍,即k/=2,一直到k2<num,若num是完全平方数,则其根在(k,2k)范围内。此方法可通过。

代码如下:

bool isPerfectSquare(int num)
{
	if (num == 1)
		return true;
	long long k = num / 2, val = 0;
	while (true)
	{
		val = k*k;
		if (val == num)
			return true;
		if (val < num)
			break;
		k /= 2;
	}
	for (long long i = k + 1; i < k * 2; i++)
	{
		val = i*i;
		if (val == num)
			return true;
		if (val > num)
			break;
	}
	return false;
}

法三:此外,想到常用的二分法,居然也是超时通不过。

代码如下:

bool isPerfectSquare(int num)
{
	int left = 0, right = num, mid = 0, tmp = 0;
	while (left <= right)
	{
		mid = (left + right) / 2;
		tmp = mid*mid;
		if (tmp == num)
			return true;
		if (tmp < num)
			left = mid + 1;
		else
			right = mid - 1;
	}
	return false;
}

法四:二分法能不过的原因还是对于大一点的数,查找的范围太广了。可结合方法二,先将查找范围确定在(k,2k),再使用二分法,显然对于比较大的数,执行效率将比法二高得多。此法亦能通过。

代码如下:

bool isPerfectSquare(int num)
{
	if (num == 1)
		return true;
	long long k = num / 2, val = 0;
	while (true)
	{
		val = k*k;
		if (val == num)
			return true;
		if (val < num)
			break;
		k /= 2;
	}
	long long left = k, right = k * 2, mid = 0;
	while (left <= right)
	{
		mid = (left + right) / 2;
		val = mid*mid;
		if (val == num)
			return true;
		if (val < num)
			left = mid + 1;
		else
			right = mid - 1;
	}
	return false;
}

  

posted on 2018-03-22 11:45  bigpotato  阅读(168)  评论(0)    收藏  举报