算法之递归算法(五)

2023-10-26

上一篇将讲解的内容是从整体流程思考递归函数的内容
这一篇我们衔接上一篇继续讲解从整体流程思考递归函数的内容。我们同样使用一个实例来分析。

【题目描述】
任何一个正整数都可以用2的幂次方表示。例如:
137=27+23+20
同时约定方次用括号来表示,即ab可表示为a(b)。由此可知,137可表示为:
2(7)+2(3)+2(0)
进一步:7=22+2+20(21用2表示)
3=2+20
所以最后137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315=210+28+25+2+1
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
【输入】 137
【输出】 2(2(2)+2+2(0))+2(2+2(0))+2(0)

这个问题看起来是比较棘手的。咋看一眼,我们能感受到其中有很多重复的操作,那就是将一个整数拆解成几个数字相加,然后在对拆解的数字再次进行拆分。这些步骤我们感受得到,但具体怎么实现呢?真是棘手。我们尝试分析一下。
1、程序首先考虑将整数 137拆解成 2^7+2^3+2^0。这与整数分解成 二进制数字是类似的。如果将 137拆解成 二进制的话,得到结果为 010001001。而对应的 1的位置正好是指数。那么我们可以不可以通过这个得到呢?答案是可以的。根据分解的步骤,我们将统计分解的次数,并在输出时提供。但需要注意的是,我们分解得到的结果是颠倒的——第一次求余得到的结果是最右侧的 1。因此,我们需要将输出的内容放在递归函数调用的后面,通过 的过程进行输出,这样就能保证在第一次输出的是最高位的 1了。

我们尝试使用程序描述这样的情况。

//n 保存分解的数字
//i 统计位数
void f(int n, int i)
{
	//如果n的值为0,是不需要分解的
	if(n == 0)
		return;
	//不是0,则需要分解,分解的时候需要对分解的数字不断除以2,已获得余数--余数才是关键
	int r = n % 2;
	f(n / 2, i + 1);	//进行下一次分解,位数相应增加1
	//如果余数为1,才有输出的必要
	if(r == 1)
		cout << "2(" << i << ")" << endl;
}
实现完这一步,我们得到 步骤1中的结果,接下来我们将继续分解。
2、我们将形如 2^7中的 7继续划分。那么也就是对程序中的 i进行划分。但 i的值是由多种数字组成。第一种 0,也就是 2(0)的形式。第二种 1,需要输出成 2的形式,并没有括号。第三种与第一种类似, i的值为 2,我们输出成 2(2)的形式。第四种 i的值大于 2,那么这时就需要将 i的值再次进行分解了,分解的过程类似于对 137的划分。

我们尝试划分一下。

void f(int n, int i)
{
	if(n == 0)
		return;
	int r = n % 2;
	f(n / 2, i +1);
	if(r == 1)
	{//对 i 进行划分情况
		if( i == 0 || i == 2)
			cout << "2(" << i << ")";
		else if(i == 1)
			cout << 2;
		else
		{//i > 2时, 需要重新划分
			//划分时,需要将位数重新归0
			cout << "2(";	//格式
			f(i, 0);
			cout << ")";
		}
	}
}
到目前位置,我们已经可以顺利的拆解各个数字了。但对于格式来说,是很糟糕的——所有数字都连在一起。题目中要求是我们使用加法将他们连接起来。那么我们可以在每一个数字输出之前输出一个 +。我们尝试进行修改,在 f(n/2, i+1)的下一行加上输出 if(r == 1) cout << "+";。添加条件是必要的——我们只在余数为 1的位置添加 +连接,而不是所有都添加。但问题随之而来,第一个位置会多一个 +,这该怎么办呢?这对我们了解程序执行过程的程度是一种考验。我们接着进行分析。
3、第一个位置输出 +。这个位置是第一次 时进行输出的,第一次 时,也就是 i处于最大值时——位数最高时。按照分解整数获得 二进制时,位数最高也就意味着 137这个数字已经分解结束了,那么它就会变为 0。此时,程序就好处理了,我们每次在程序运行时,都将 n的值进行改变,并在输出 +时判断 n是否为 0。如果为 0,也就意味着最高位,也就不能输出了。

我们对程序进行改进。

void f(int n, int r)
{
	if(n == 0)
		return 0;
	int r = n % 2;
	n /= 2;	//在调用函数的过程中修改n的值
	f(n, i + 1);	
	if(n != 0 && r == 1)
		cout << "+";
	if(r == 1)
	{
		if(i == 0 || i == 2)
			cout << "2(" << i << ")";
		else if(i == 1)
			cout << 2;
		else
		{
			cout << "2(";
			f(i, 0);
			cout << ")";
		}
	}
}

那么通过这样的分析,这道题的完整程序就已经实现了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法之递归算法(五) 的相关文章

  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 最牛B的编码套路

    最近 我大量阅读了Steve Yegge的文章 其中有一篇叫 Practicing Programming 练习编程 写成于2005年 读后令我惊讶不已 与你所相信的恰恰相反 单纯地每天埋头于工作并不能算是真正意义上的锻炼 参加会议并不能锻
  • js 字符串函数总结(splice()、split()·····)

    1 自己比较易混淆的splice substring substr slice方法 第一个参数指定子字符串开始位置 第二个参数表示子字符串最后一个字符后面的位置 substring方法 第一个参数指定子字符串开始位置 第二个参数表示子字符串
  • C++执行程序的过程

    C 执行程序的过程 C 的源程序是以 cpp作为后缀的 C语言则是 c cpp保存也可以兼容 为了使计算机能够执行高级语言的代码 必须对源程序做个处理 用编译器把源程序处理成计算机可以识别的二进制目标程序 一般目标程序的后缀为 obj 编译
  • 新手必看,10个常见的Python运行时错误

    初入门的 Python小白 在运行代码时免不了会遇到一些错误 刚开始可能看起来比较费劲 随着代码量的积累 熟能生巧 当遇到一些运行时错误时能够很快的定位问题原题 我整理了常见的 10 个错误 希望能够帮助到大家 1 忘记在 if for d
  • C/C++将数据读写到指定地址

    0 背景 外设私有 内部 DMA在访问core内sram时 发现没有权限 也就是说 core不可作为slave设备被访问 导致外设的dma模式无法使用 但这并没有问题 我们可以将数据写到固定的地址 外部sram上 即可 下面介绍几种常用的方
  • 那个当年的三本学渣,为啥最后进了大厂?

    自我介绍 我是一名普通的三本大学生 自学开发 相继经历了接外包 创业 合伙人跑路等一系列事情 从一开始对于计算机的一无所知到现在拿到了一线互联网企业的special offer 磕磕碰碰 一路走来 可谓辛酸苦辣 大一小白 我就读的专业偏计算
  • ELK介绍及部署安装运用

    1 ELK简介 ELK表示 Elasticsearch Logstash Kibana 三个开源软件的缩写 是集成这三个软件于一体的日志分析及全文搜索解决方案 被广泛应用于实时日志处理 文档索引和搜索 以及数据的多维查询和统计分析等领域 数
  • 每日一题:二分答案

    二分答案 题目 Daimayuan Online Judge 首先读入 n 和 k 然后读入序列 a 接下来使用 l 和 r 表示最小值的猜测区间 由于题目中规定了最小值和元素范围 因此我们可以将上界设置为 1e18 下界设置为 1 二分查
  • 开机无法进入,chroot无法切换真实根环境

    1 开机效果图 2 关机 调整开机顺序 从光驱启动 进入挽救模式 3 尝试切换到真实根环境 失败 错误提示说 进入shell失败了 没有这个文件 4 ls查看发现这个文件是有的 但是这个文件是在挽救模式下的 真实根下面是没有的 5 真实根的
  • linux spi设备使用,linux spi驱动开发学习(一)-----spi子系统架构

    linux spi驱动开发学习 一 spi子系统架构 一 spi设备 各定义在include linux spi h structspi device structdevice dev 设备文件 structspi master maste
  • 蒙特卡洛法简述

    蒙特卡洛法简述 一 简介 1 蒙特卡洛方法又称随机模拟法 随机抽样技术 是一种随机模拟方法 蒙特卡洛法使用随机数 伪随机数 以概率和统计理论方法为基础 将所要求解的问题同一定的概率模型相互联系 用计算机实现统计模拟和抽样 以获得问题近似解的
  • LabVIEW FPGA PCIe开发讲解-实战篇:实验61:PCIe DMA+8位ADC(模拟数据采集卡)

    1 实验内容 现在很多电脑PC或者工控机主板上面都集成了PCIe插座 可以直接插入PCIe板卡 优点是卡槽标准 插拔简单 传输速度极快 对于高速采集测试测量领域 PCIe用途非常广泛 最大极限带宽可以到6 6GB s 这个速度可以直接用来做
  • Qt:依据ChatGpt生成Qt可选择扇形按钮

    目录 引言 1 生成过程 1 1 饼图 2 2 扇形图 3 3 可选择扇形按钮 1 4 新的扇形画法 GraphicItem 2 训练过程 3 错误原因 4 涉及知识点 引言 因为项目需要绘制一个中间为圆心 包含数个扇形的可选择按钮 正好C
  • php16进制转换为字符串

    因项目需求对接一个java的接口 密匙是16进制 使用php内置函数 hex2bin str abc key XXXXX res hash hmac sha1 str hex2bin key false hash hmac最后一个参数tru
  • 【Python】进阶之 MySQL入门教程

    文章目录 数据库概述 Mysql概述 Mysql安装与使用 Navicat安装和使用 Mysql终端指令操作 Mysql和python交互 订单管理案例实现 数据库概述 数据库的由来 发展历程 说明 人工管理阶段 用纸带等进行数据的存储 文
  • linux 编写防火墙脚本

    防火墙脚本实际上就是个shell脚本 使用shell脚本来设置防火墙策略的优点在于 可以预先加载一些必要的内核模块 设置环境参数 可以使用变量和灵活控制程序结构 便于脚本文件的重用和移植 常见的防火墙脚本通常包括以下部分 1 设置网段 网卡
  • 01背包和完全背包

    1 01背包 有 N 件物品和一个容量为 V 的背包 第 i 件物品的费用是 c i 价值是 w i 求解将哪些物品装入背包可使价值总和最大 这是最基础的背包问题 特点是 每种物品仅有一件 可以选择放或不放 用子问题定义状态 即 f i v
  • MD5签名 Java转换C#

    Java 代码 import java security MessageDigest import org apache commons codec binary Base64 public static String doSign Str
  • STM32系统嘀嗒定时器实现1ms中断事件

    int main 系统定时器实现周期性1000hz中断事件 即1ms SysTick Config SystemCoreClock 1000 void SysTick Handler void static uint32 t cnt
  • 算法之递归算法(五)

    上一篇将讲解的内容是从整体流程思考递归函数的内容 这一篇我们衔接上一篇继续讲解从整体流程思考递归函数的内容 我们同样使用一个实例来分析 题目描述 任何一个正整数都可以用2的幂次方表示 例如 137 27 23 20 同时约定方次用括号来表示