leetcode入门刷题笔记(2)-C/C++

将数字变成 0 的操作次数

来源:力扣(LeetCode)题源链接

题目:给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。

小白尝试:

int numberOfSteps(int num){
	int cnt=0;
	while(num>0){
		if(0==num%2)	//当num为偶数时除以2
			num=num/2;
		else			//当num为奇数时减1
			num--;	
		cnt++;			//操作步数count加一
	}
return cnt;
}

这是最简单易懂的解决方法之一

可以注意到,上面的if(0==num%2)是常量0在左侧,这种代码风格习惯的好处在于可以避免双等号写成单等号,意外赋值,而导致程序的逻辑错误。比如不小心写成if(0=num%2),此时编译器就会报错,因为我们不能给常量0赋值。当然现代的一些IDE的代码审查工具也可以帮助检测出此类错误,这只是一种编程风格的选择

leetcode官方解答:

int numberOfSteps(int num) {
    int ret = 0;
    while (num) {
        ret += (num > 1 ? 1 : 0) + (num & 0x01);
        num >>= 1;
    }
    return ret;
}

(num > 1 ? 1 : 0) 这是一个(三目运算符)条件表达式,检查num是否大于1。若num>1,则ret+1;若num<=1,则不增加ret的值,直接进入下一步
(num & 0x01)这是位与运算,用于判断num奇偶。若num为奇数,则会返回1;若为偶数,则返回0;因此这一步假如num是奇数的话,ret+1
num >>= 1这将num右移了一位。当num为奇数的话,结果为(num-1)/2;当num为偶数的话,则等价于num/2
由此,该函数的逻辑就是,
①先判断num>1?,是的话操作步数+1。因为只要num>1,无论奇偶,步数都会+1
②判断num是否为奇数?是奇数的话操作步数+1
③操作num
假设num=7,执行①②③之后,ret=2,num=3;
再执行①②③操作,ret=4,num=1;
再执行②③操作,ret=5, num=0;

再po个评论区大佬的解答:
递归解法

int numberOfSteps(int num) {
        if(num==0){
            return ;
        }
        step++;
        if(num%2==0){
             numberOfSteps(num/2);
        }else {
             numberOfSteps(num-1);
        }
}

当然更简约一点可以这样:

int numberOfSteps(int num) {
        if(num==0){
            return ;
		return (num%2==0 ? numberOfSteps(num/2):numberOfSteps(num-1)) +1;
}

假设我们调用numberOfSteps(15),过程如下:

  1. 15是奇数,所以调用numberOfSteps(14)然后加1。此时还未返回,继续递归。
  2. 14是偶数,所以调用numberOfSteps(7)然后加1。继续深入。
  3. 7是奇数,调用numberOfSteps(6)然后加1。
  4. 6是偶数,调用numberOfSteps(3)然后加1。
  5. 3是奇数,调用numberOfSteps(2)然后加1。
  6. 2是偶数,调用numberOfSteps(1)然后加1。
  7. 1是奇数,调用numberOfSteps(0)然后加1。
  8. 当num=0时,根据基础情况返回0。

从这最后一步(num=0时返回0),递归开始回溯,每回溯一层,就相当于给总的步数加1,因为它代表了到达那个状态需要的额外一步操作(无论是除以2还是减1)。所以,当从最底层(num=0)回溯到最初的调用(num=15)时,实际上每一步都为最终结果贡献了自己的“+1”,累计了从原始输入到0所需的总步数。

因此,虽然直接看最后一次基础递归调用返回了0,但这个0是一个触发点,让所有的递归调用能够开始回溯并累加它们各自计算的步数,从而最终得出原始num减少到0所需的总步数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值