bigpotato

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

Given a positive integer n and you can do operations as follow:

  1. If n is even, replace n with n/2.
  2. If n is odd, you can replace n with either n + 1 or n - 1.

What is the minimum number of replacements needed for n to become 1?

 

Example 1:

Input:
8
Output:
3
Explanation:
8 -> 4 -> 2 -> 1

Example 2:

Input:
7
Output:
4
Explanation:
7 -> 8 -> 4 -> 2 -> 1
or
7 -> 6 -> 3 -> 2 -> 1

 
给定一个正整数n,若n是偶数,将其除以2,若n是奇数,可替换为n-1或n+1。求将n转换为1所需的最小次数。
 
分析:
  这道题乍一看很简单,输入n,当n为偶数就除以2,当n为奇数时就加1或减1,一直循环,直至最后n=1即可。
  但实际上呢?
  当n为奇数时,我统一采取减1,提交发现当n=65535时,我的计算结果是30次,而期望得到的是17次!分析发现,当n=65535时,加1变为65536=216,所以只需要17次(1次加1,16次除2),而减1的话,n=65534,除2为32767,又是奇数,得再次执行减1,一直执行到最后,就多出了13次。所以当n为奇数时,单纯的减1是不行的。减1不行那就改为加1,但提交的时候发现当n=3时又错了,因为加1后变为4了,再除2次2才会为1,总共3次;而减1的话直接就等于2了,再除1次2就为1,共2次。
  仔细观察,发现当n+1为4的倍数时(3、7是特例,先不管),执行加1次数会更少,比如15:若加1,15->16->8->4->2->1,共5次;若减1,15->14->7->6->3->2->1,共6次。因为若n+1为4的倍数,则n+1=4k,至少可连续除2次才会为奇数(具体次数视k而定),而n-1=4k-2,执行1次除2就为奇数了,而若得出的奇数不是1,是需要转化为偶数(加减1)再继续的,次数必然会更多。对于n=7的情况,加减1的次数都是一样的,不用特殊对待。特例就剩3了,当n=3时,减1更快。
  那如何确定n+1会不会是4的倍数呢?我们可以从二进制来看,加1变为4的倍数的数,其最低2位为11,因为已经判断是奇数了,因此当n为奇数时,判断其二进制的倒数第2位是否为1即可,3是特例要特殊处理。
  最终代码如下:
int integerReplacement(int n)
{
	if (n == 1)
		return 0;
	long long val = n;
	int cnt = 0;
	while (val > 1)
	{
		if (val & 1)
			if ((val & 2) && (val != 3))
				val++;
			else
				val--;
		else
			val >>= 1;
		cnt++;
	}
	return cnt;
}

  

posted on 2018-03-23 15:29  bigpotato  阅读(112)  评论(0)    收藏  举报