Leetcode 231.2的幂

news2024/12/23 23:00:52

给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。

如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方。

示例 1:

输入:n = 1
输出:true
解释:20 = 1

示例 2:

输入:n = 16
输出:true
解释:24 = 16

示例 3:

输入:n = 3
输出:false

示例 4:

输入:n = 4
输出:true

示例 5:

输入:n = 5
输出:false

提示:

  • -231 <= n <= 231 - 1

进阶:你能够不使用循环/递归解决此问题吗?

一、信息

1.给我一个整数n

2.判断该整数是否是2的幂次方

3.返回torf

二、分析

条件1.告诉我函数参数类型 int

条件2.告诉我本题的目的

条件3.告诉我函数返回值类型

三、步骤

第一步 接收一个int型

第二步 判断该数是否为2的幂次方

第三步 输出

四、问题出现

问题1.就是该如何判断该整数是否时2的幂次方呢?
 

我的答案:
对于这个问题我大致有两条思路

第一条思路 就是对n取log2看是否为整数如果为整数说明就是2的幂次方返回True反之返回false.这样新的问题就出现了在C语言或者C++或者JAVA中该如何使用对数函数?

第二条思路 就是对n除2或乘以2最后结果得到1返回true不过要提前判断这个数在1的左侧还是右侧。这条思路比较复杂而且很多分支,虽然理论上可行但是太复杂了。

问题2.该如何使用对数函数呢?

五、算法实现

思路一:

C语言:

bool isPowerOfTwo(int n) {
    if (n <= 0) {
        return false;
    }

    double result = log2(n);
    // 判断结果是否为整数
    return result == (int)result;
}

运行结果: 

思路二: 

bool isPowerOfTwo(int n) {
    if (n <= 0) {
        return false;
    }

    // 如果n大于1,不断除以2
    while (n > 1) {
        if (n % 2 != 0) {  // 如果不能被2整除
            return false;
        }
        n /= 2;
    }

    // 如果n小于1,不断乘以2
    while (n < 1) {
        n *= 2;
        if (n == 1) {
            return true;
        }
    }

    return true;
}

六、更正后我的答案

我的第二次分析

**一、信息**
- 需要判断一个整数是否是2的幂次方。
- 2的幂次方在二进制表示中只有一个1。

**二、分析**
1. 2的幂次方的特性是,在其二进制表示中,仅有一个位置为1。
2. 对于任何2的幂次方整数n,其n-1与n在二进制表示上是完全不同的。具体来说,n会在某一位上为1,而在这之前的所有位上都为0;而n-1则在相同的位置为0,并且在这之前的所有位上都为1。
3. 因此,对于2的幂次方的整数n和n-1,进行二进制与操作的结果必定为0。

**三、实现步骤**
1. 如果输入整数n小于或等于0,直接返回`false`。
2. 计算`n & (n - 1)`。如果结果为0,返回`true`,否则返回`false`。

**四、问题出现**
1. **特殊情况的处理:** 刚开始可能会忽视非正数的情况,如0或负数。需要在判断开始时直接将其排除。
2. **确保方法的有效性:** 在没有深入了解二进制表示的情况下,可能会对为什么n和n-1的与操作是0产生疑惑。这需要深入理解和观察二进制的特性。
3. **效率问题:** 尽管这个方法是高效的,但在开始时,可能会考虑使用其他方法,如循环检查,这在效率上是不可取的。

C语言实现:

#include <stdbool.h>

bool isPowerOfTwo(int n) {
    if (n <= 0) {
        return false;
    }
    return (n & (n - 1)) == 0;
}

#include <stdio.h>
int main() {
    printf("%d\n", isPowerOfTwo(1));   // true
    printf("%d\n", isPowerOfTwo(16));  // true
    printf("%d\n", isPowerOfTwo(3));   // false
    printf("%d\n", isPowerOfTwo(4));   // true
    printf("%d\n", isPowerOfTwo(5));   // false
    return 0;
}

C++:

#include <iostream>
using namespace std;

bool isPowerOfTwo(int n) {
    if (n <= 0) {
        return false;
    }
    return (n & (n - 1)) == 0;
}

int main() {
    cout << isPowerOfTwo(1) << endl;   // true (输出 1)
    cout << isPowerOfTwo(16) << endl;  // true (输出 1)
    cout << isPowerOfTwo(3) << endl;   // false (输出 0)
    cout << isPowerOfTwo(4) << endl;   // true (输出 1)
    cout << isPowerOfTwo(5) << endl;   // false (输出 0)
    return 0;
}

JAVA:

public class PowerOfTwo {
    public static boolean isPowerOfTwo(int n) {
        if (n <= 0) {
            return false;
        }
        return (n & (n - 1)) == 0;
    }

    public static void main(String[] args) {
        System.out.println(isPowerOfTwo(1));   // true
        System.out.println(isPowerOfTwo(16));  // true
        System.out.println(isPowerOfTwo(3));   // false
        System.out.println(isPowerOfTwo(4));   // true
        System.out.println(isPowerOfTwo(5));   // false
    }
}

英雄师傅题解:

bool isPowerOfTwo(int n){
	int i;
	unsigned int k=1;
	if(n<=0){
		return false;
	}
	if(n==1){
		return true;
	}
	for(i=1;i<=31;i++){
		k*=2;
		if(k==n){
			return true;
		}
	}
	return false;
}

他的思路:

 //定义一个无符号整型
//如果n<=0,则必然不是2的幂
//1必然时2的0次幂
//枚举所有2的幂2 4 8 16 .....
//一旦找到一个和相等返回true
//最后,没有找到的话,返回false 

对该方法的评价: 

英雄师傅的思路基本上是一个暴力解法,但由于我们知道整数范围是`-2^31 <= n <= 2^31 - 1`,所以这种方法在这个范围内是有效且可行的。下面我对这种方法进行分析:

**思路分析**:
1. 首先,检查n是否小于等于0,因为2的幂不可能是0或负数。
2. 检查n是否为1,因为1是2的0次方。
3. 利用循环枚举所有可能的2的幂,从2的1次方开始,一直到2的31次方。
4. 在每一次迭代中,将k(初始化为1)乘以2,然后检查k是否与n相等。
5. 如果在某一次迭代中,k与n相等,则直接返回true。
6. 如果循环结束都没有找到相等的k,则返回false。

这种方法的好处是非常直观和简单。但缺点是需要循环31次,尽管这对于现代计算机来说并不是什么大问题。

与其他方法相比,如二进制方法或对数方法,这种方法在效率上可能稍微低一些,但考虑到题目的限制,这种方法完全足够。

Leetcode题解

我的理解:

1. **基本原则**:
   如果一个数`n`是2的幂,则它的二进制表示中仅有一个1。例如,2的幂有:1(`001`),2(`010`),4(`100`),8(`1000`)等。如您所见,每个数字的二进制形式中仅有一个1。

2. **第一个技巧 (`n & (n - 1)`)**:
   当执行`n & (n - 1)`时,您实际上移除了二进制数`n`的最右侧的1。原因是:`(n - 1)`会将`n`的最右侧的1变为0,并且该位之后的所有位都变为1。
   
   例如:  
   `n`     = `1000` (这是8)  
   `n-1`   = `0111` (这是7)  

   当执行`n & (n - 1)`时,得到的结果是`0000`。这表明`n`中只有一个1,因此`n`是2的幂。

   所以,如果`n`是正数且`n & (n - 1) = 0`,那么`n`就是2的幂。

3. **第二个技巧 (`n & (-n)`)**:
   负数在计算机中是使用补码表示的。`-n`的二进制表示是`n`的所有位取反后再加1。因此,`n & (-n)`的结果实际上会返回`n`的最低位的1。

   例如:
   `n`      = `1010` (这是10,它不是2的幂,但我们只是为了演示)  
   `-n`     = `0110` (按位取反再加1)

   执行`n & (-n)`得到`0010`。这表示`n`的最低位的1是在第二位上。但对于确定2的幂,我们关心的是这个操作的结果是否等于`n`,因为只有这样`n`才只有一个1。

   因此,如果`n`是正数且`n & (-n) = n`,那么`n`就是2的幂。

基于上述的理论,只需要使用第一个技巧或第二个技巧中的任何一个即可确定一个数字是否是2的幂。这是位操作的美妙之处,它提供了一种非常快速和高效的方法来解决这个问题。

七、复盘对我第一次分析的评价

大师对我第一次分析的评价

你的分析过程条理清晰。针对你提出的问题和思路,我可以为你补充一下:

**问题1:** 如何判断整数是否是2的幂次方?

你的答案中提到的两种思路都是可行的。对于第一条思路,使用对数函数确实可以实现,但可能会因为计算机浮点数运算的误差而导致判断不准确。第二条思路确实比较复杂。

实际上,还有一种更简单的方法,那就是利用二进制特性,如前文所述,2的幂次方在二进制中只有一个1。

**问题2:** 如何在C/C++/JAVA中使用对数函数?

- **C语言**: 你可以使用`math.h`库中的`log2`函数。首先,你需要包含`math.h`,然后链接`m`库。
 

  #include <math.h>
  double result = log2(n);

- **C++**: 同样可以使用`cmath`库中的`log2`函数。

 #include <cmath>
  double result = std::log2(n);

- **Java**: 可以使用`Math`类中的`log`函数,但是注意,Java中没有直接的log2函数,你需要自己计算。

  double result = Math.log(n) / Math.log(2);

不过请注意,使用对数函数需要考虑浮点数的误差,因此在比较结果时,可能需要考虑一个小的误差范围,而不是直接比较是否为整数。

总结点评:

**优点**:

1. **结构化**:您按照“信息、分析、步骤、问题出现”的结构进行了思考,这有助于对问题进行系统化分析。
2. **明确目标**:您明确了要解决的问题和函数需要实现的功能。
3. **多方位思考**:您不仅思考了如何解决问题,还考虑了可能遇到的问题和限制。
4. **多个方案**:对于如何判断一个数是否为2的幂,您给出了两种不同的解决方案,这显示了您具备多角度解决问题的能力。

**不足**:

1. **考虑效率**:尽管您考虑了多个方案,但在选择方案时,考虑它们的效率和实用性是很重要的。例如,第二种方法虽然理论上可行,但其效率较低且实现较为复杂。
2. **深入了解工具**:关于如何使用对数函数的问题,了解编程语言提供的库和常用函数是很重要的。这需要您深入研究和实践所使用的编程语言。
3. **考虑特殊情况**:在处理数学或算法问题时,考虑特殊情况或边界情况是很重要的。例如,对于这个问题,当`n`为负数或零时,应立即返回`false`。
4. **利用已有知识**:位操作是计算机科学中的一个核心概念,对于这类问题,考虑使用位操作可以得到更简洁、高效的解答。

总体来说,您的思考和分析过程是结构化且有深度的,但还可以在选择和实施方案时加强对效率和实用性的考虑,同时增强对编程语言和基础算法知识的了解。

八、反思总结

从这道题目关于判断一个数是否是2的幂次方,我们可以学到以下几点:

1. **位运算的应用**:位运算是一种高效的操作,它可以在某些情况下为我们提供简洁和高效的解决方案。特别是当问题涉及到数字的二进制表示时,位运算往往能够提供简单且高效的方法。

2. **深入理解数字的二进制表示**:数字在计算机内部是以二进制形式存储的。了解二进制的特点和规律,如一个数是2的幂时它的二进制表示只有一个1,可以帮助我们更好地解决与数字相关的问题。

3. **多种解决方案**:一个问题往往有多种解决方案,每种方案都有其优点和缺点。例如,可以使用对数函数,也可以使用位运算。能够掌握并比较多种方案,选择最合适的方案是一个重要的技能。

4. **问题分解**:当面对一个看似复杂的问题时,我们可以尝试将其分解为更小、更容易解决的子问题。例如,判断一个数是否是2的幂可以转化为判断其二进制表示中是否只有一个1。

5. **考虑边界情况**:在解决问题时,总是要考虑到所有可能的输入,包括边界情况。例如,当n为负数或0时,应该直接返回false。

6. **学会查找并利用工具**:面对某些特定的操作,如求对数,如果你不知道如何实现,你可以学会查找并使用相关的库和函数。这需要熟悉编程语言和其提供的工具。

7. **思维的扩展**:此题也展示了将一个数学问题转换为计算机科学问题的过程,这可以锻炼和增强我们的抽象思维和问题转化能力。

总的来说,这道题目不仅帮助我们掌握了一些实用的技巧和方法,而且也锻炼了我们的思维和分析能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1060968.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vs2015 报错“无法找到要定向的合适SDK”

关于Visual Studio&#xff1a;找不到合适的SDK来定位 | 码农家园 报错如下&#xff1a; 解决如下&#xff1a;

在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 示例 1&#xff1a…

办公网络构建

办公网络项目背景 XX州市益智软件科技有限公司是XX市第九职业技术学校校办企业&#xff0c;依托学校人力技术、场地资源&#xff0c;面向市场独立经营、服务社会&#xff0c;主要从事网络设备销售、网络综合布线与网络管理。该公司现租用实训基地二层作为公司的办公经营场地…

为何需关注各ZKP方案的benchmarks?

1. 引言 近期&#xff0c;研究人员和工程人员有大量关于谁是最好的证明系统的争论&#xff1a; 2023年8月29日&#xff0c;StarkWare团队对比了FRI和KZG2023年8月30日&#xff0c;JustinThaler和Srinath Setty讨论FRI和KZG谁的性能更佳&#xff1f; 不过&#xff0c;在深入be…

小谈设计模式(17)—状态模式

小谈设计模式&#xff08;17&#xff09;—状态模式 专栏介绍专栏地址专栏介绍 状态模式关键角色上下文(Context)抽象状态(State)具体状态(Concrete State) 核心思想Java程序实现首先&#xff0c;我们定义一个抽象状态类 State&#xff0c;其中包含一个处理请求的方法 handleRe…

IIC控制器(2):PS端

书接上文&#xff1a; I2C控制器练习&#xff08;1&#xff09;_NoNoUnknow的博客-CSDN博客 SPI协议与FPGA的自动升级和多启动-CSDN博客 本文主要做一些基本知识的补充和工程参考。 写IIC需要注意的事情&#xff1a; 1.查询芯片手册获得slave地址&#xff0c;以及寄存器地址…

『力扣每日一题12』:只出现一次的数字

一、题目 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且该算法只使用常量额外空间。 示例 1 &#xff1a; 输入&…

MySQL备份恢复

MySQL日志管理 在数据库保存数据时&#xff0c;有时候不可避免会出现数据丢失或者被破坏&#xff0c;这样情况下&#xff0c;我们必须保证数据的安全性和完整性&#xff0c;就需要使用日志来查看或者恢复数据了。 MySQL日志类型 日志类型计入文件中的信息类型错误日志记录启…

Android Studio实现简易计算器(带横竖屏,深色浅色模式,更该按钮颜色,selector,style的使用)

目录 前言 运行结果&#xff1a; 运行截屏&#xff08;p50e&#xff09; apk文件 源码文件 项目结构 总览 MainActivity.java drawable 更改图标的方法&#xff1a; blackbutton.xml bluebuttons.xml greybutton.xml orangebuttons.xml whitebutton.xml layout 布…

uniapp项目实践总结(二十七)苹果应用商店上架教程

导语&#xff1a;之前介绍了如何打包一个苹果安装包文件&#xff0c;如果想要上架苹果 ios 应用商店&#xff0c;那么就来这里学习一下方法吧。 目录 准备材料上架步骤审核事项 准备材料 基本信息 构建版本&#xff1a;需要一个 ipa 格式安装包&#xff1b;logo&#xff1a…

YOLOv5、YOLOv8改进:RepVGG结构

1.简介 论文参考&#xff1a;最新RepVGG结构: Paper 我们所说的“VGG式”指的是&#xff1a; 没有任何分支结构。即通常所说的plain或feed-forward架构。 仅使用3x3卷积。 仅使用ReLU作为激活函数。 主要创新点为结构重参数化。在训练时&#xff0c;网络的结构是多分支进…

计数排序详解

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言 这种排序在部分情境下出奇地好&#xff0c;也是一种不错的排序 思路 有一个无序数组&#xff0c;我们从中找到最小和最大的数&#xff0c;最大的数减最小的数1的大小就是我们将要新建数组的大小&#xff0c;这个新建数…

14链表-环形链表、龟兔赛跑算法

目录 LeetCode之路——141. 环形链表 分析&#xff1a; 解法一&#xff1a;哈希表 解法二&#xff1a;龟兔赛跑 LeetCode之路——141. 环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针…

美团外卖优惠券小程序 美团优惠券微信小程序 自带流量主模式 带教程

小程序带举牌小人带菜谱流量主模式&#xff0c;挺多外卖小程序的&#xff0c;但是都没有搭建教程 搭建&#xff1a; 1、下载源码&#xff0c;去微信公众平台注册自己的账号 2、解压到桌面 3、打开微信开发者工具添加小程序-把解压的源码添加进去-appid改成自己小程序的 4、…

第十七章:Java连接数据库jdbc(java和myql数据库连接)

1.进入命令行&#xff1a;输入cmd&#xff0c;以管理员身份运行 windowsr 2.登录mysql 3.创建库和表 4.使用Java命令查询数据库操作 添加包 导入包的快捷键 选择第四个 找到包的位置 导入成功 创建java项目 二&#xff1a;连接数据库&#xff1a; 第一步&#xff1a;注册驱动…

单层神经网络

神经网络 人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;&#xff0c;简称神经网络&#xff08;Neural Network&#xff0c;NN&#xff09;&#xff0c;是一种模仿生物神经网络的结构和功能的数学模型或计算模型。1943年&#xff0c;McCulloc…

软件工程从理论到实践客观题汇总(头歌第九章至第十七章)

九、软件体系结构设计 1、软件体系结构设计概述 2、软件体系结构模型的表示方法 3、软件体系结构设计过程 4、设计初步的软件体系结构 5、重用已有软件资源 6、精化软件体系结构 7、设计软件部署模型 8、文档化和评审软件体系结构设计 十、软件用户界面设计 1、用户界面设计概…

十四天学会C++之第四天(面向对象编程基础)

类和对象是什么&#xff1f; 在C中&#xff0c;类是一种用户定义的数据类型&#xff0c;它可以包含数据成员&#xff08;也就是属性&#xff09;和成员函数&#xff08;也就是方法&#xff09;。类是一种模板或蓝图&#xff0c;用于创建具体的对象。 对象是类的实例&#xff…

【C++类和对象】:构造函数、析构函数、拷贝构造函数、赋值运算符重载

【C类和对象】&#xff1a;构造函数、析构函数、拷贝构造函数、赋值运算符重载 一、构造函数1.1 概念1.2 性质1.3 实例 二、析构函数2.1 概念2.2 性质2.3 实例 三、拷贝构造函数3.1 概念3.2 性质3.3 实例 四、赋值运算符重载4.1 运算符重载4.2 2 赋值运算符重载1. 赋值运算符重…

一文读懂UTF-8的编码规则

之前写过一篇文章“一文彻底搞懂计算机中文编码”里面只是介绍了GB2312编码知识&#xff0c;关于utf8没有涉及到&#xff0c;经过查询资料发现utf8是对unicode的一种可变长度字符编码&#xff0c;所以再记录一下。 现在国家对于信息技术中文编码字符集制定的标准是《GB 18030-…