实现一个函数,对一个正整数n,算得到1需要的最少操作次数。操作规则为:如果n为偶数,将其除以2;如果n为奇数,可以加1或减1;一直处理下去。
例子:
func(7) = 4,可以证明最少需要4次运算
n = 7
n-1 6
n/2 3
n-1 2
n/2 1
要求:实现函数(实现尽可能高效) int func(unsign int n);n为输入,返回最小的运算次数。给出思路(文字描述),完成代码,并分析你算法的时间复杂度。
#include <iostream>
using namespace std;
int func(unsigned int n)
{
if(n == 1)
return 0;
if(n % 2 == 0)
return 1 + func(n/2);
if(n == 3)
return 2;
if(n&2)
return 1 + func(n+1);
else
return 1 + func(n-1);
}
int func1(int n)
{
int m=n;
int *s=new int[n+1];
s[1]=0;
s[2]=1;
for(int i=3;i<=m;i++)
{
if(i%2==0)
{
s[i]=s[i/2]+1;
}
else
{
int c1=s[i-1]+1;
int c2=s[(i+1)/2]+2;
if(c1>c2)
{
s[i]=c2;
}
else
{
s[i]=c1;
}
}
}
return s[n];
}
int func2(unsigned int n)
{
int k = 0;
int t, s;
while(n > 1)
{
//如果是偶数
if((n & 0x00000001) == 0)
{
n = n >> 1;
k++;
continue;
}
//如果是奇数,+1还是-1的标准是:n'这个整数的各个位中为1的个数最少,如果相同,当然-1.
t = n - 1;
t = (t & 0x55555555) + ((t & 0xaaaaaaaa) >> 1);
t = (t & 0x33333333) + ((t & 0xcccccccc) >> 2);
t = (t & 0x0f0f0f0f) + ((t & 0xf0f0f0f0) >> 4);
t = (t & 0x00ff00ff) + ((t & 0xff00ff00) >> 8);
t = (t & 0x0000ffff) + ((t & 0xffff0000) >> 16);
s = n + 1;
s = (s & 0x55555555) + ((s & 0xaaaaaaaa) >> 1);
s = (s & 0x33333333) + ((s & 0xcccccccc) >> 2);
s = (s & 0x0f0f0f0f) + ((s & 0xf0f0f0f0) >> 4);
s = (s & 0x00ff00ff) + ((s & 0xff00ff00) >> 8);
s = (s & 0x0000ffff) + ((s & 0xffff0000) >> 16);
if(s < t)
{
n = n + 1;
}
else
{
n = n - 1;
}
k ++;
}
return k;
}
int _tmain(int argc, _TCHAR* argv[])
{
int i;
for (i = 1; i < 51; i++)
{
#if 1
cout << i << ":" << func(i) << ", ";
if (i%5 == 0)
cout << endl;
#endif
if (func(i) != func1(i))
cout << i << func(i) << func1(i) << endl;
}
system("pause");
return 0;
}