华为OD机试真题:分糖果【2022 Q1 Q2 |200分】

题目描述
小明从糖果盒中随意抓一把糖果,每次小明会取出一半的糖果分给同学们。

当糖果不能平均分配时,小明可以选择从糖果盒中(假设盒中糖果足够)取出一个糖果或放回一个糖果。

小明最少需要多少次(取出、放回和平均分配均记一次),能将手中糖果分至只剩一颗。

输入描述:
抓取的糖果数(<10000000000):15

输出描述:
最少分至一颗糖果的次数:5

示例 1
输入:15
输出:5

解释:
(1) 15+1=16;
(2) 16/2=8;
(3) 8/2=4

(4)4/2=2

(5)2/2=1

说明:因为测试用例有限,所以用解法1和解法2硬匹配前2000个结果,都是一样的,所以可以确认解法1是对的

#解题想法1:题目的要求是快速将糖分到1,所以1/2操作是最佳操作,能快速使糖数减少。
通过观察发现,有两个特点,一是,比如15,15+1是2^n,比15-1接下来再循环次数少,
从而推出,如果m+1或m-1是2^n,那么直接可以快速循环到1(一刀一半);二是,如果m+1是4的倍数,
那么可以三步快速刀到m+1的1/4,因为之前先判断了m-1、m或m+1不是2的次幂,m也不是偶数,
那么m是奇数,如果操作m-1,(m-1)/2如果不符合前面的判定条件那么又会是奇数,
有重复上述操作而增加步骤数,当然这里特例是m=3,那么减1再/2更快



def f2(m):


    l = [2 ** i for i in range(1, int(m / 2))]
    # print(l)

    res = 0

    while m != 1:
        if m - 1 in l:
            m = m - 1
            res += 1
        elif m + 1 in l:
            m = m + 1
            res += 1
        elif m in l:
            m = int(m / 2)
            res += 1
        else:
            if m % 2 == 0:
                m = int(m / 2)
                res += 1
            else:
                if (m+1)%4==0:
                    if m>3:
                        m=m+1
                        res+=1
                    else:
                        m=m-1
                        res+=1
                else:
                    m = m - 1
                    res += 1
        # print(m, res)
    return res


解题思想2:硬算

import collections
def f1(n):

    queue = collections.deque()
    queue.append(n)
    def bfs(queue,target,depth):#depth即遍历几层后找到了1
        while queue:
            depth += 1
            for i in range(len(queue)):
                cur = queue.popleft()
                if cur == target:
                    return depth
                queue.append(cur+1)
                queue.append(cur-1)
                if cur%2 == 0:
                    queue.append(cur/2)
    return bfs(queue,1,-1)
    # print(bfs(queue,1,-1)) #之所以初始的depth为-1是因为第一次手中的糖果数量
如果就是目标数量,则需要的操作次数为0





  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值