【C++】递归 1241 - 角谷猜想 1108 - 正整数N转换成一个二进制数

news2024/11/26 13:35:24

文章目录

  • 一、问题:1241 - 角谷猜想
  • 二、问题:1108 - 正整数N转换成一个二进制数
  • 三、总结
  • 四、感谢

一、问题:1241 - 角谷猜想

类型:有规律的循环、递归。


题目描述:

日本一位中学生发现一个奇妙的定理,请角谷教授证明,而教授无能为力,于是产生了角谷猜想。
猜想的内容:任给一个自然数,若为偶数则除以 2 ,若为奇数则乘 3 加 1 ,得到一个新的自然数后按上面的法则继续演算。若干次后得到的结果必为 1 。
请编写代码验证该猜想:求经过多少次运算可得到自然数 1 。
如:输入 22 ,则计算过程为。
22/2=11
11×3+1=34
34/2=17
17×3+1=52
52/2=26
26/2=13
13×3+1=40
40/2=20
20/2=10
10/2=5
5×3+1=16
16/2=8
8/2=4
4/2=2
2/2=1
经过 15 次运算得到自然数 1 。

输入:

一行,一个正整数 n 。( 1≤n≤20000 )

输出:

一行,一个整数,表示得到 1 所用的运算次数。

样例:

输入:

22

输出:

15

在这里插入图片描述
在这里插入图片描述


1.分析问题

  1. 已知:一个正整数 n 。
  2. 未知:得到 1 所用的运算次数。
  3. 关系:角谷猜想。

2.定义变量

  • 定义并读入一个整数n;
	//二、数据定义 
	int n;

3.输入数据

	//三、数据输入 
	cin>>n;

4.数据计算

  1. 定义全局变量c用于记录操作次数。

  2. 定义一个名为op的递归函数,参数为需要进行运算的整数n。

  3. 当n不等于1时,进入递归:

  • 如果n是偶数,则对n进行除以2的操作,并以结果作为新的n调用op函数;

  • 如果n是奇数,则对n进行乘以3再加1的操作,并以结果作为新的n调用op函数;

  • 每进行一次上述操作(无论是除以2还是乘以3加1),全局计数器c加1。

int c=0; 

void op(int n){
	if(n!=1){
		if(n%2==0){
			op(n/2);
		}else{
			op(n*3+1);
		}
		++c;
	}
	
	
}
  • 调用op(n)开始执行角谷猜想的计算流程;
	//四、数据计算 
	op(n);

5.输出结果

  • 输出操作次数c,即从输入的n到达1所需经过的步骤数。
	//五、输出结果 
	cout<<c;
	return 0;

完整代码如下:

#include <bits/stdc++.h> // 引入C++标准库的头文件,包含大部分常用函数和数据结构
using namespace std; // 使用std命名空间,方便调用其中的标准库函数

int c = 0; // 定义全局变量c,用于记录执行操作(变换)的次数

// 定义递归函数op,参数为整数n
void op(int n) {
    if (n != 1) { // 如果当前数值n不等于1,则继续进行以下操作
        if (n % 2 == 0) { // 如果n是偶数
            op(n / 2); // 将n除以2后作为新的输入值调用op函数(遵循角谷猜想的规则)
        } else { // 否则,即当n是奇数时
            op(n * 3 + 1); // 根据角谷猜想将n乘以3并加1后作为新的输入值调用op函数
        }
        ++c; // 在每次执行完一次操作(无论是否改变n的值)后,计数器c增加1
    }
}

int main() {
    // 分析问题:实现角谷猜想(Collatz Conjecture),即对于任意正整数n,通过特定规则变换,最终都能到达1

    int n; // 定义变量n,用于存储用户输入的初始数值

    // 数据输入
    cin >> n;

    // 数据计算
    op(n); // 调用op函数对给定的n执行角谷猜想的操作流程

    // 输出结果
    cout << c; // 输出从初始数值n到1所经历的操作次数

    return 0; // 程序正常结束,返回0
}

思路二:累计计算递归次数,然后层层返回。思路一致,但这次op函数的实现有所不同,它返回从输入数值n到1所经历的操作步数。

#include <bits/stdc++.h> // 引入C++标准库头文件
using namespace std; // 使用std命名空间

// 定义递归函数op,参数为整数n,返回从n到达1所需的操作步数
int op(int n) {
    if (n != 1) { // 如果当前数值n不等于1,则继续进行以下操作
        if (n % 2 == 0) { // 如果n是偶数
            return 1 + op(n / 2); // 将n除以2,并在返回结果上加1(表示这一步操作),然后调用op函数
        } else { // 否则,即当n是奇数时
            return 1 + op(n * 3 + 1); // 根据角谷猜想将n乘以3并加1,并在返回结果上加1,然后调用op函数
        }
    } else { // 当n等于1时,结束递归
        return 0; // 返回0,因为从1开始无需额外的操作步数
    }
}

int main() {
    // 分析问题:实现角谷猜想,计算给定正整数n经过特定规则变换达到1所需要的步骤数

    // 二、数据定义
    int n, c; // 定义变量n存储用户输入的初始数值,c存储变换所需的操作步数

    // 三、数据输入
    cin >> n;

    // 四、数据计算
    c = op(n); // 调用op函数计算从n到1需要的操作步数,并将结果赋值给变量c

    // 五、输出结果
    cout << c; // 输出从n到1所经历的操作步数

    return 0; // 程序正常结束,返回0
}

思路三:同样用于实现角谷猜想,与前一个版本相比,这次op函数多了一个参数c,用来记录递归过程中累计的操作步数。这样每次函数调用时可以直接传递和累加操作步数,无需全局变量来统计。

#include <bits/stdc++.h> // 引入C++标准库头文件
using namespace std; // 使用std命名空间

// 定义递归函数op,参数为整数n(当前数值)和c(累计操作步数)
int op(int n, int c) {
    if (n != 1) { // 如果当前数值n不等于1,则继续进行以下操作
        if (n % 2 == 0) { // 如果n是偶数
            return op(n / 2, 1 + c); // 将n除以2,并在累计操作步数上加1,然后调用op函数
        } else { // 否则,即当n是奇数时
            return op(n * 3 + 1, 1 + c); // 根据角谷猜想将n乘以3并加1,并在累计操作步数上加1,然后调用op函数
        }
    } else { // 当n等于1时,结束递归
        return c; // 返回累计的操作步数,表示从初始值到达1所需要的步骤数
    }
}

int main() {
    // 分析问题:实现角谷猜想,计算给定正整数n经过特定规则变换达到1所需要的步骤数

    // 二、数据定义
    int n, c = 0; // 定义变量n存储用户输入的初始数值,c初始化为0,用于存储变换所需的操作步数

    // 三、数据输入
    cin >> n;

    // 四、数据计算
    c = op(n, c); // 调用op函数计算从n到1需要的操作步数,第二个参数c作为累计步数传入,并接收最终结果

    // 五、输出结果
    cout << c; // 输出从n到1所经历的操作步数

    return 0; // 程序正常结束,返回0
}

思路四:实现了角谷猜想的非递归版本。通过一个while循环来迭代地对输入的自然数n进行处理,直到n变为1为止,并在过程中累计进行了多少次运算。最后输出到达1所需的操作步数。

#include <iostream>
using namespace std;

int main() {
    // 一、分析问题
    // 已知:我们有一个自然数n
    // 未知:需要计算从这个自然数开始,经过多少次运算(若为偶数则除以2,若为奇数则乘3加1)可以得到自然数1
    // 关系:根据给定规则迭代变换数字n

    // 二、数据定义
    int n, count = 0; // 定义变量n存储用户输入的初始数值,count用于记录进行运算的次数

    // 三、数据输入
    cin >> n; // 输入待计算的自然数n

    // 四、数据计算
    while (n != 1) { // 当n不等于1时,继续执行循环内的操作
        if (n % 2 == 0) { // 如果n是偶数
            n /= 2; // 将n除以2
            count++; // 操作次数加1
        } else { // 若n是奇数
            n = n * 3 + 1; // 根据角谷猜想将n乘以3并加1
            count++; // 操作次数加1
        }
    } 

    // 五、输出结果
    cout << count << endl; // 输出到达1所需的运算次数
    return 0; // 程序正常结束,返回0
}

二、问题:1108 - 正整数N转换成一个二进制数

类型:字符串、进制转换


题目描述:

输入一个不大于 32767 的整数 n ,将它转换成一个二进制数。

输入:

输入只有一行,包括一个整数 n (0≤n≤32767)。

输出:

输出只有一行。

样例:

输入:

100

输出:

1100100

输入:

0

输出:

0

在这里插入图片描述


1.分析问题

  1. 已知:整数 n。
  2. 未知:转换成一个二进制数。
  3. 关系:进制转换、递归。

2.定义变量

  • 定义一个字符串 s 来存储转换后的二进制数。
  • 定义整数变量 n,用于接收用户输入的待转换的十进制数。
	//二、数据定义 
	int n;
	string s=""; 

3.输入数据

通过 cin>>n; 从标准输入读取一个十进制整数 n。


	//三、数据输入
	cin>>n;

4.数据计算

  • 4.1定义一个名为binary的递归函数,接受一个整数n和一个空字符串s作为参数。
string binary(int n, string s){
    char c; // 用于存储n对2取余的结果(0或1)并转换为字符
    // 基本情况:当n等于0时,返回当前已经拼接好的二进制字符串s
    if(0 == n){
        return s;
    } 
    // 递归步骤:当n不等于0时,计算n除以2的商,并将其与n对2取余的结果(c)一起传递给下一次函数调用
    else{
        c = n % 2 + '0'; // 将余数转换为字符'0'或'1'
        return binary(n / 2, c + s); // 调用binary函数并将结果与当前的余数拼接到前边
    }
}
  • 4.2 调用binary函数进行二进制转换。
	s=binary(n,s);

5.输出结果

  • 判断字符串 s 是否为空(即 “”==s),如果为空说明输入的十进制数是0,则直接输出0;否则输出转换得到的二进制字符串 s。
	//五、输出结果 
	if(""==s){
		cout<<0;
	}else{
		cout<<s;
	}
	return 0;

完整代码如下:

#include <bits/stdc++.h> // 包含标准输入输出库
using namespace std; // 使用标准命名空间

// 定义一个名为binary的递归函数,接受一个整数n和一个空字符串s作为参数
string binary(int n, string s){
    char c; // 用于存储n对2取余的结果(0或1)并转换为字符
    // 基本情况:当n等于0时,返回当前已经拼接好的二进制字符串s
    if(0 == n){
        return s;
    } 
    // 递归步骤:当n不等于0时,计算n除以2的商,并将其与n对2取余的结果(c)一起传递给下一次函数调用
    else{
        c = n % 2 + '0'; // 将余数转换为字符'0'或'1'
        return binary(n / 2, c + s); // 调用binary函数并将结果与当前的余数拼接到前边
    }
}

int main(){
    // 数据定义部分
    int n; // 输入的十进制整数
    string s = ""; // 初始化一个空字符串,用于存储转换后的二进制数

    // 数据输入部分
    cin >> n; // 从标准输入读取一个整数赋值给n

    // 数据计算部分
    s = binary(n, s); // 调用binary函数进行二进制转换

    // 输出结果部分
    // 判断字符串 s 是否为空(即 ""==s),如果为空说明输入的十进制数是0,则直接输出0;.
    if ("" == s){
        cout << 0;
    } 
    // 其他情况下,输出已转换好的二进制字符串s
    else{
        cout << s;
    }

    return 0; // 主函数返回0,表示程序正常结束
}

思路二:

非递归版本。

使用 while(n) 循环,在 n 不等于0的情况下持续进行以下操作:

  • 计算 n 除以2的余数,并将其赋值给 x。
  • 将 x 转换为字符,通过 c=x+‘0’;,这里利用了 ASCII 码中 ‘0’ 至 ‘9’ 的连续性。
  • 将字符 c 添加到字符串 s 的开头,使用 s=c+s; 进行拼接,这样可以确保生成的二进制数是从低位到高位的顺序。
  • 将 n 更新为其除以2的商,即 n/=2;。

完整代码如下:

#include <bits/stdc++.h> // 包含C++标准库中的所有头文件(不推荐在生产环境中使用,建议只包含所需头文件)
using namespace std; // 引入std命名空间以简化代码

int main() {
    // 一、分析问题部分(注释中说明)
    // 需要将一个已知的整数 n 转换成二进制形式表示。

    // 二、数据定义
    string s; // 定义一个字符串s用于存储转换后的二进制数
    int n, x; // n为待转换的十进制整数,x为计算过程中暂存的余数
    char c; // c用于将余数转换成字符'0'或'1'后添加到s中

    // 三、数据输入
    cin >> n; // 从标准输入读取十进制整数n

    // 四、数据计算
    while (n) { // 当n非零时进行循环
        x = n % 2; // 计算n除以2的余数
        c = x + '0'; // 将余数转换为对应的字符(0或1)
        s = c + s; // 将字符c添加到字符串s的开头,这样得到的是逆序的二进制数
        n /= 2; // 更新n为除以2的商,以便下一次循环继续求余操作
    }

    // 五、输出结果
    if ("" == s) { // 如果转换后得到的二进制数为空(即n原来是0)
        cout << 0; // 输出0
    } else {
        cout << s; // 否则输出转换得到的二进制字符串
    }

    return 0; // 程序正常结束,返回值为0
}

三、总结

  1. 递归版本:
  • 优点:代码结构简洁清晰,直接体现了问题的递归特性。

  • 缺点:如果输入的数值较大,可能会导致较深的递归栈,占用较多内存,甚至可能触发栈溢出。此外,递归版本对于理解递归过程和控制递归深度的要求较高。

  1. 非递归版本:
  • 优点:不会因为递归深度过深而导致栈溢出问题,且对于循环次数有更直观的控制。同时,对于理解和调试代码而言,非递归版本有时更为直观易懂。

  • 缺点:相比递归版本,代码量稍多一些,逻辑稍微复杂。

四、感谢

如若本文对您的学习或工作有所启发和帮助,恳请您给予宝贵的支持——轻轻一点,为文章点赞;若觉得内容值得分享给更多朋友,欢迎转发扩散;若认为此篇内容具有长期参考价值,敬请收藏以便随时查阅。

每一次您的点赞、分享与收藏,都是对我持续创作和分享的热情鼓励,也是推动我不断提供更多高质量内容的动力源泉。期待我们在下一篇文章中再次相遇,共同攀登知识的高峰!

在这里插入图片描述

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

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

相关文章

如何判断可编程电子负载是否合格?

可编程电子负载是一种可以模拟实际负载的电子设备&#xff0c;广泛应用于电源、电池、充电器等产品的测试和研发。判断可编程电子负载是否合格&#xff0c;需要从以下几个方面进行考量&#xff1a; 精度是衡量电子负载性能的重要指标&#xff0c;包括电流精度、电压精度、功率精…

ImportError: Could not import docarray python package解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Qt 使用QListView实现简约美观的聊天窗口

今天和大家分享一个使用QListView来展现聊天窗口的历史记录的例子, 因为聊天记录可能会有很多, 所以使用试图-模型的方式更加合理 这是最终效果: ChatHistoryModel继承自QAbstractListModel , ChatHistoryViewDelegate继承自QStyledItemDelegate, 这个例子最关键的就是在QSty…

Keil MDK安装armcc V5编译器

不知道从什么时候开始&#xff0c;Keil MDK默认不支持V5的编译器了&#xff0c;里面默认只有V6的编译器&#xff0c;设置界面跟V5有很大的差异不太熟悉。最可怕的是&#xff0c;之前使用V5编译的工程&#xff0c;换成V6编译器后居然报错...虽然修改一下应该也可以正常编译&…

几种常用的查看Ros话题的命令

1、查看 rqt_tf_tree rosrun rqt_tf_tree rqt_tf_tree 2、查看ros node 关系 rqt_graph 3、列出所有话题 rostopic list 4、查看某一话题的类型 以 /scan 为例 rostopic type /scan 5、查看某个数据类型包含哪些数据 rosmsg show sensor_msgs/LaserScan sensor_…

Gitlab修改仓库权限为public、Internal、Private

Public&#xff08;公开&#xff09;&#xff1a;所有人都可以访问该仓库&#xff1b; Internal&#xff08;内部&#xff09;&#xff1a;同一个GitLab群组或实例内的所有用户都可以访问该仓库&#xff1b; Private&#xff08;私人&#xff09;&#xff1a;仅包括指定成员的用…

2024年最新《国际预警期刊》正式更新!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、国际期刊预警名单的变化&#xff1f;二、课程案例展示&#xff08;篇幅有限仅展示部分&#xff09;1.【热图系列】2.【九象限图系列】3.【富集分析系列】4.【机…

自动化测试基础——Pytest框架之YAML详解以及Parametrize数据驱动

文章目录 一、YAML详解1.YAML作用2.YAML语法结构3.YAML数据类型3.1.对象3.2.数组3.3.标量 4.YAML的引用5.YAML类型转换 二、YAML的读写与清空1.YAML的读2.YAML的写3.YAML的清空 三、pytest的parametrize简单数据驱动四、pytest的parametrize结合yaml实现数据驱动五、解决pytest…

数据库期末速成100分训练,附练手数据库原件及教程

本文提供下面数据库代码的数据库原件&#xff0c;下载后可使用 教程如下&#xff1a; 1.打开sql sever 2.找到数据库 3.右键数据库点击“附加”&#xff0c;然后点击“添加” 4.导入数据库原件&#xff0c;点击确定 ps&#xff1a;如果没有sqlsever 或者页面编辑器&#x…

基于SSM的农业信息管理系统的设计与实现(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的农业信息管理系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;…

JavaScript中的innerHTML、value属性,零基础开发web前端

CSS篇 让一个元素水平垂直居中&#xff0c;到底有多少种方案&#xff1f;浮动布局的优点&#xff0c;缺点&#xff1f;清除浮动的方式&#xff1f;使用display:inline-block会产生的问题&#xff1f;解决方法&#xff1f;布局题&#xff1a;div垂直居中&#xff0c;左右10px&a…

LeNet5实战——衣服分类

搭建模型训练代码&#xff08;数据处理、模型训练、性能指标&#xff09;——> 产生权重w ——>模型结构c、w测试 配置环境 Pycharm刚配置的环境找不到了-CSDN博客 model.py 导入库 import torch from torch import nn from torchsummary import summary 模型搭…

【HarmonyOS】Dev Eco Studio4.0安装教程

目录 下载安装开发工具配置 下载 Dev Eco Studio4.0下载连接→https://developer.huawei.com/consumer/cn/next/deveco-studio/ 安装 点击Next 选择安装目录。点击Next 勾选创建桌面快捷方式和环境变量&#xff0c;点击Next 点击Install&#xff0c;安装 等待安装 选…

android开发视频教程百度网盘,深入浅出Android

基于Linux的pc启动过程 我们都知道&#xff0c;所有的程序软件包括操作系统都是运行在内存中的&#xff0c;然而我们的操作系统一般是存放在硬盘上的&#xff0c;当我们按下开机键的时候&#xff0c;此时内存中什么程序也没有&#xff0c;因此需要借助某种方式&#xff0c;将操…

JavaWeb环境配置 IDE2022版

一、新建一个javaweb文件 文件名可以自己随意改 二、给建立的项目添加框架支持 勾选Web Application,点击确定 建立成功界面&#xff0c;会生成一个新的web文件夹 三、配置tomcat 1、两种打开配置文件方式&#xff1a; 第一种 第二种 2、打开后&#xff0c;点击号&#xf…

Redis面试问题纯享版

基础内容 1、简单介绍以下你了解的Redis 2、对比一下Redis和Memcache的异同&#xff1f; 3、为什么MySQL选用Redis作为缓存&#xff1f; 4、详细聊聊你对Redis各种数据类型的了解&#xff1f; 5、Redis中五种基本数据类型的底层数据结构是什么样的&#xff1f; Redis线程模型…

结合大象机器人六轴协作机械臂myCobot 280 ,解决特定的自动化任务和挑战!(上)

项目简介 本项目致力于探索和实现一种高度集成的机器人系统&#xff0c;旨在通过结合现代机器人操作系统&#xff08;ROS&#xff09;和先进的硬件组件&#xff0c;解决特定的自动化任务和挑战。一部分是基于Jetson Orin主板的LIMO PPRO SLAM雷达小车&#xff0c;它具备自主导航…

flutterpush消息,Android开发两年

如何进阶Android&#xff1f; 有些东西你不仅要懂&#xff0c;而且要能够很好地表达出来&#xff0c;能够让面试官认可你的理解&#xff0c;例如Handler机制&#xff0c;这个是面试必问之题。有些晦涩的点&#xff0c;或许它只活在面试当中&#xff0c;实际工作当中你压根不会…

LeetCode_24_中等_两两交换链表中的节点

文章目录 1. 题目2. 思路及代码实现&#xff08;Python&#xff09;2.1 递归2.2 迭代 1. 题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换…

微信小程序接入百度地图(微信小程序插件)使用文档

第一步配置域名 :在微信公众平台登录后配置服务域名称:https://apis.map.qq.com 第二步申请密钥 申请开发者密钥申请地址 第三步使用插件 选择添加插件 搜索腾讯位置服务地图选点 选择要授权的小程序 授权完毕会在这里显示插件信息 第四步查看使用文档 跳转至文…