一个数转化成1的最小步数

在算法贴吧上看到的一个问题 :   http://tieba.baidu.com/p/264968529

把一个正整数变为1,求最少的步数?

具体是这样的:

   如果这个数是偶数,那么直接除2;

   如果是奇数,加1或减1后再除2;

   这样反复,一直到变为1,求最少需要几步?


例如 func(7)=4; 
int func(unsigned int n);
n为输入的的正整数。

 

 

/**
     * 找出一个数转成1的最小步数
     * 分析奇数 2进制 如果最后一位是1 倒数第2位是0 如果这时候加1 那么就会导致除2之后要再次加1或者减1所以有可能增加步骤
     * 如果倒数第2位是1 那么加1 的话 把倒数第2个也变成0  节约了倒数第2位的加减操作 当然可能会让倒数第3位要加减 但是没关系
     * 这个只是相当于把倒数第2位的操作放到倒数第三位 但是如果是连续多个1就会节约步骤
     *
     * 但是3的话比较特殊   3虽然是11  但是减1的话会让他变成2 加1变成4多了一位
     *其他的ok  xx01 这个显然是 减1
     *  xx11 这个也是加1 因为前面还有 所以没关系
     *
     * @param num
     * @return
     */
    public static int findMinStep(int num) {
        int three = 3;
        int step = 0;
        int tmp;
        while (num > 1) {
            //这个比较特殊
            if (num == 3) {
                step += 2;
                break;
            }
            tmp = num & three;
            if (tmp == 3) {
                step += 2;
                num = (num + 1) >> 1;
            } else if (tmp == 1) {
                step += 2;
                num = (num - 1) >> 1;
            } else {
                step++;
                num = num >> 1;
            }
        }
        return step;
    }

 

3的时候 比较蛋疼 差点考虑错了~  3虽然是11 但是它的前面那个1不是必须处理的 所以加1就不合理了!

 

 

http://blog.csdn.net/mathe/article/details/1492206  看到一个证明  呵呵 跟我的思想差不多 不过它的看起来更厉害 呵呵 ~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值