5_机试_递归和分治

news2024/11/30 2:37:20

一、递归

本章介绍程序设计中的另一个非常重要的思想一递归策略。递归是指函数直接或间接调用自身的一种方法,它通常可把一个复杂的大型问题层层转化为与原问题相似但规模较小的问题来求解。递归策略只需少量的程序就可描述解题过程所需的多次重复计算,因此大大减少了程序的代码量。


1、n的阶乘–清华大学

描述

输入一个整数n,输出n的阶乘(每组测试用例可能包含多组数据,请注意处理)

输入描述:

一个整数n(1<=n<=20)

输出描述:

n的阶乘

示例1

输入:

3

输出:

6

题解:

递归的两个关键点:
1. 递归出口
2. 递归调用
#include <iostream>
#include <cstdio>

using namespace std;

/**
 * 求num的阶乘
 * 注意阶乘的结果很大,所以返回值类型要是long
 * @param num 
 * @return 
 */
long factorial(int num) {
    if (num == 0 || num == 1) {
        /*
         * 特殊值
         * 0和1的阶乘都是1
         */
        return 1;
    }
    return num * factorial(num - 1);
}

/**
 * n的阶乘--清华大学
 * @return
 */
int main() {
    int n;
    while (cin >> n) {
        cout << factorial(n) << endl;
    }

    return 0;
}

2、汉诺塔III–杭州电子科技大学

描述

约19世纪末,在欧洲的商店中出售一种智力玩具:在一块铜板上有三根杆,最左边的杆自上而
下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的圆盘全部移到右边的杆上,条件是一次只能移动一个圆盘,并且不允许大圆盘放在小圆盘的上面。现在我们改变这个游戏的玩法:不允许直接从最左(右)边移动到最右(左)边(每次移动一定是移到中间杆或从中间杆移出),也不允许大圆盘放到小圆盘的上面。Daisy已经做过原来的汉诺塔问题和汉诺塔Ⅱ问题,但碰到这个问题时,她想了很久都无法解决。请你帮助她。现在有N个圆盘,她至少需要多少次移动才能把这些圆盘从最左边移到最右边?

输入描述:

包含多组数据,每次输入一个N值(1 <= N <= 35)。

输出描述:

对于每组数据,输出移动最小的次数。

示例1

输入:

1
3
12

输出:

2
26
531440

题解:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

#include <iostream>
#include <cstdio>

using namespace std;

long long Hanoi01(int n) {
    if (n == 1) {
        return 2;
    } else {
        return 3 * Hanoi01(n - 1) + 2;
    }
}

long long Hanoi02(int n) {
    long long ans = 1;
    for (int i = 0; i < n; ++i) {
        ans *= 3;
    }
    ans -= 1;
    return ans;
}

/**
 * 汉诺塔III--杭州电子科技大学
 * @return
 */
int main() {
    int n;
    while (cin >> n) {
        cout << Hanoi01(n) << endl;
        //cout << Hanoi02(n) << endl;
    }

    return 0;
}

二、分治

分治法(Divide and Conquer)是另一个非常重要的算法。

分治法字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多个子问题,子问题之间互相独立且与原问题相同或相似。之后再把子问题分成更小的子问题,以此类推,直到最后的子问题可以简单地直接求解,原问题的解即子问题的解的合并。

由于分治法产生的子问题往往与原问题相同且模式更小,这就为使用递归策略求解提供了条件。

在这种情况下,通过反复利用分治手段,可以使子问题的规模不断缩小,最终缩小到可以直接求解的情况。在从过程中会导致了递归过程的产生。分治与递归就像一对孪生兄,经常同时应用在算法设计中,这也是将分治法和递归策略放在同一章中进行讲解的原因。

分治法的步骤如下:
1. 分:将问题分解为规模更小的子问题。
2. 治:将这些规模更小的子问题逐个击破。
3. 合:将已解决的子问题合并,最终得出"母"问题的解。

分治法 和 贪心策略 
相同点:问题分解
区别:
	1. 分治法--子问题可能会继续分解
	2. 贪心策略--子问题将无需继续分解

1、Fibonacci–上海交通大学

描述

The Fibonacci Numbers{0,1,1,2,3,5,8,13,21,34,55…} are defined by the recurrence: F0=0 F1=1 Fn=Fn-1+Fn-2,n>=2 Write a program to calculate the Fibonacci Numbers.

输入描述:

Each case contains a number n and you are expected to calculate Fn.(0<=n<=30) 。

输出描述:

For each case, print a number Fn on a separate line,which means the nth Fibonacci Number.

示例1

输入:

1

输出:

1

题解:

三种解法:
1. 分治法--O(2ⁿ)
2. 递推法--O(n)
3. 矩阵快速幂--O(logn)
分治法
分为 F(n-1)F(n-2)
将规模为N的问题分解为两个规模分别为N-1、N-2的子问题,不断分解,直到问题规模小于0或者1,便可直接得到子问题的答案。
之后将子问题的答案相加,便可得到母问题的答案。
虽然分治法不是此题的最优解法,但其思想还是值得学习的。

#include <iostream>
#include <cstdio>

using namespace std;

int fibonacci(int n) {

    if (n == 1 || n == 0) {
        return n;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

/**
 * Fibonacci--上海交通大学
 * @return
 */
int main() {
    int n;
    while (cin >> n) {
        cout << fibonacci(n) << endl;
    }

    return 0;
}


/*
 * 递推法
 */
#include <iostream>
#include <cstdio>

using namespace std;

const int MAX = 35;

int fibonacci[MAX];

void init() {
    fibonacci[0] = 0;
    fibonacci[1] = 1;
    /*
     * 从索引2开始
     */
    for (int i = 2; i < MAX; ++i) {
        fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
    }
}

/**
 * Fibonacci--上海交通大学
 * @return
 */
int main() {
    init();
    int n;
    while (cin >> n) {
        cout << fibonacci[n] << endl;
    }

    return 0;
}

在这里插入图片描述

/*
 * 矩阵快速幂
 */
#include <iostream>
#include <cstdio>

using namespace std;

/**
 * 矩阵维数
 */
const int DIMENSION = 2;

/**
 * 矩阵
 */
struct Matrix {
    int row;
    int col;
    int matrix[DIMENSION][DIMENSION];

    Matrix(int row, int col) {
        this->row = row;
        this->col = col;
    }
};

/**
 * 矩阵乘法
 * @param x
 * @param y
 * @return
 */
Matrix multiply(Matrix x, Matrix y);

/**
 * 矩阵求幂
 * @param x
 * @return
 */
Matrix quickPower(Matrix x, int n);

/**
 * 打印矩阵
 * @param x
 */
void printMatrix(Matrix x);


/**
 * Fibonacci--上海交通大学
 * @return
 */
int main() {
    int n;
    while (cin >> n) {
        Matrix fibonacci = Matrix(2, 2);
        fibonacci.matrix[0][0] = 1;
        fibonacci.matrix[0][1] = 1;
        fibonacci.matrix[1][0] = 1;
        fibonacci.matrix[1][1] = 0;

        Matrix power = quickPower(fibonacci, n);
        Matrix tmp = Matrix(2, 1);
        tmp.matrix[0][0] = 1;
        tmp.matrix[1][0] = 0;
        Matrix ans = multiply(power, tmp);
        /*
         * 可以打印矩阵进行验证
         */
        //printMatrix(ans);
        cout << ans.matrix[1][0] << endl;

    }

    return 0;
}

Matrix multiply(Matrix x, Matrix y) {
    Matrix ans(x.row, y.col);
    for (int i = 0; i < ans.row; ++i) {
        for (int j = 0; j < ans.col; ++j) {
            ans.matrix[i][j] = 0;
            for (int k = 0; k < x.col; ++k) {
                ans.matrix[i][j] += x.matrix[i][k] * y.matrix[k][j];
            }
        }
    }
    return ans;
}

Matrix quickPower(Matrix x, int n) {
    Matrix ans = Matrix(x.row, x.col);
    for (int i = 0; i < ans.row; ++i) {
        for (int j = 0; j < ans.col; ++j) {
            if (i == j) {
                ans.matrix[i][j] = 1;
            } else {
                ans.matrix[i][j] = 0;
            }
        }
    }

    while (n != 0) {
        if (n % 2 == 1) {
            ans = multiply(ans, x);
        }
        n = n >> 1;
        x = multiply(x, x);
    }

    return ans;
}

void printMatrix(Matrix x) {
    for (int i = 0; i < x.row; ++i) {
        for (int j = 0; j < x.col; ++j) {
            if (j == 0) {
                cout << x.matrix[i][j];
            } else {
                cout << " " << x.matrix[i][j];
            }
        }
        cout << endl;
    }
}

2、二叉树–北京大学

描述

img

如上所示,由正整数1,2,3……组成了一颗特殊二叉树。我们已知这个二叉树的最后一个结点是n。现在的问题是,结点m所在的子树中一共包括多少个结点。 比如,n = 12,m = 3那么上图中的结点13,14,15以及后面的结点都是不存在的,结点m所在子树中包括的结点有3,6,7,12,因此结点m的所在子树中共有4个结点。

输入描述:

输入数据包括多行,每行给出一组测试数据,包括两个整数m,n (1 <= m <= n <= 1000000000)。

输出描述:

对于每一组测试数据,输出一行,该行包含一个整数,给出结点m所在子树中包括的结点的数目。

示例1

输入:

3 12
0 0

输出:

4

题解:

对于求根结点为m的树中有多少结点数目这个问题,可以将问题分解为求它左子树和右子树的结点数目这两个相同的子问题。
在得到其左、右子树的结点数目后,加上结点m本身便可得到问题的解。

当结点m大于时,以m为根结点的树为空,那么该树的结点数目必定为0,这个便是这个问题可被轻松求解的底层子问题,也是递归出口。
#include <iostream>
#include <cstdio>

using namespace std;

int countNode(int m, int n) {
    if (m > n) {
        /*
         * 递归出口
         * 因为一共就n个顶点,所以m>n时结束即可
         */
        return 0;
    } else {
        /*
         * 根节点+左子树的节点数+右子树的节点数
         */
        return 1 + countNode(2 * m, n) + countNode(2 * m + 1, n);
    }
}

/**
 * 二叉树--北京大学
 * @return
 */
int main() {
    int m;
    int n;
    while (cin >> m >> n) {
        cout << countNode(m, n) << endl;
    }

    return 0;
}

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

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

相关文章

谈谈Java多线程离不开的AQS

如果你想深入研究Java并发的话&#xff0c;那么AQS一定是绕不开的一块知识点&#xff0c;Java并发包很多的同步工具类底层都是基于AQS来实现的&#xff0c;比如我们工作中经常用的Lock工具ReentrantLock、栅栏CountDownLatch、信号量Semaphore等&#xff0c;而且关于AQS的知识点…

DDR4 信号说明

SDRAM Differential Clock :Differential clocks signal pairs , pair perrank . The crossing of the positive edgeand the negative edge of theircomplement are used to sample thecommand and control signals on theSDRAMSDRAM差分时钟&#xff1a;差分时钟信号对&#…

MagicThoughts|让ChatGPT变得更智能的Finetuned数据集

近两个月&#xff0c;ChatGPT无疑都是AI领域最炙手可热的话题。而它的成功&#xff0c;也引发了行业内外对于对话式AI、LLM模型商业化应用可能性的思考。诚然&#xff0c;尽管就目前来看ChatGPT对大部分问答都能基本做到“对答如流”。但是&#xff0c;ChatGPT本质上依旧是预训…

Flutter Modul集成到IOS项目

Flutter Modul集成到IOS项目中1. 创建一个Flutter Modul2.在既有应用中集成Flutter Modul2.1 Flutter的构建模式选择2.1.1 debug模式2.1.2 Release模式2.1.3 Podfile 模式2.2 Cocoapods管理依赖库集成方式2.3 直接在Xcode中集成framework2.4 Local Network Privacy Permissions…

采用 spring 配置文件管理Bean

文章目录采用 spring 配置文件管理Bean一、安装配置Maven二、Spring 框架1、Spring 官网三、Spring 容器演示-采用Spring配置文件管理Bean1、创建Manev项目2、添加Spring依赖3、创建杀龙骑士类4、创建勇敢骑士类5、采用传统方式让勇敢骑士完成杀龙任务6、采用Spring 容器让勇敢…

创建Ubuntu虚拟机与Windows共享的文件夹

目录 1、Windows创建一个共享文件夹 2、在虚拟机的设置中选择Windows下的共享文件夹 3、在Ubuntu中查看共享文件夹 1、Windows创建一个共享文件夹 该共享文件夹可以被Windows和Ubuntu访问&#xff0c;需要注意的是&#xff0c;Ubuntu在共享目录下的一些操作会受到限制&…

图解经典电路之OCL差分功放-三极管分立器件电路分析

下面从简到繁,从框架到细节的顺序讲解电路。即先讲框架,然后逐渐添加电路细节,所以大家跟上思路。 1、第一步,尽可能的抽象这个电路,等效如下: 图二 OCL等效电路 整个OCL电路,可以等效为一个大功率的运放,加上几个电阻电容构成了一个同向放大器,就是这么简单。 为了便…

Linux常用命令---系统常用命令

Linux系统常用命令场景一&#xff1a; 查看当前系统内核版本相关信息场景二&#xff1a; sosreport 命令场景三&#xff1a; 如何定位并确定命令&#xff1f;场景四&#xff1a;查看当前系统运行负载怎场景五&#xff1a; 查看当前系统的内存可用情况场景六&#xff1a;查看网卡…

【DOTA】目标检测数据集介绍与使用

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 DOTA 数据集简单介绍 1. 正文 1.1 简介 数据集包含来自不同的传感器和平台的航拍图。每张图像的像素尺寸在 800 800 到 20,000 20,000 之间&#xf…

如何编写接口测试用例?

接口测试用例如何编写&#xff1f;下面简单给大家讲解一下。 接口测试用例是目前软件开发中不可或缺的一个重要部分&#xff0c;因此编写接口测试用例同样重要。 接口测试用例的作用非常明显&#xff0c;它能够帮助我们了解产品正在考验、调整它如何表现在特定情境之下、产品是…

2023金三银四,测试人还能找到好工作吗?

按照往年的惯例&#xff0c;春节后复工的 3 月、4 月是人员跳槽最频繁的时候&#xff0c;俗称“金三银四”。然而&#xff0c;市场大环境的影响&#xff0c;很多行业感受到了一丝寒冷的气息。我们以为受影响比较轻的互联网行业&#xff0c;头上也充满乌云&#xff0c;所谓互联网…

2023年浙江交安安全员考试题库及答案

百分百题库提供交安安全员考试试题、交安安全员考试真题、交安安全员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 50.根据《建设工程安全生产管理条例》第65条规定&#xff0c;施工单位有下列&#xff08;&#xff09;行…

JavaScript高级程序设计读书分享之3章——3.5操作符

JavaScript高级程序设计(第4版)读书分享笔记记录 适用于刚入门前端的同志 目录 操作符 一元操作符 递增/递减操作符 一元加和减 布尔操作符 逻辑非 逻辑与 逻辑或 乘性操作符 乘法操作符 除法操作符 取模操作符 加性操作符 加法操作符 减法操作符 关系操作符 相等操…

使用python将EXCEL表格中数据转存到数据库

使用Python将excel表格中数据转存到数据库 1. 思路&#xff1a; 1&#xff09; 使用python读取excel表格中数据 2&#xff09;根据数据生成sql语句 3&#xff09;批量运行sql语句 2. 代码&#xff1a; import pandas as pddef readExcel(path, excel_file):return pd.read_e…

低代码开发平台|制造管理-质检管理搭建指南

1、简介1.1、案例简介本文将介绍&#xff0c;如何搭建制造管理-质检管理。1.2、应用场景质检分别包括来料质检、过程质检、成品质检&#xff0c;来料质检在采购物料入库后会自动发起来料质检的流程&#xff0c;质检合格才可提交结束流程&#xff1b;过程检是在生产过程中的质检…

小程序-滑块+iconfont下载本地使用

效果 <view style"padding: 5px;"><movable-area style"width: 100%;height: 100%;"><movable-view direction"all" style"width: 50px;height: 50px;background-color: green"> </movable-view></movable…

推荐一些不常见的搜索引擎

5.雅虎网来自 Yahoo.com 的屏幕截图&#xff0c;2023 年 2 月截至 2022 年 1 月&#xff0c;Yahoo.com&#xff08;Verizon Media&#xff09;的搜索市场份额为 11.2%。雅虎的优势在于多元化&#xff0c;除搜索外还提供电子邮件、新闻、金融等服务。二十多年来&#xff0c;雅虎…

MyBatis 之一(概念、创建项目、操作模式、交互流程)

1. MyBatis 是什么MyBatis 是一款优秀的持久层框架MyBatis 也是一个 ORM &#xff08;Object Relational Mapping&#xff09;框架&#xff0c;即对象关系映射它支持自定义 SQL、存储过程以及高级映射MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作MyBatis…

SpringAOP笔记【JavaEE】

SpringAOP 一、AOP理解 AOP是一种思想&#xff0c;SpringAOP是一个框架&#xff0c;提供了一种对AOP思想的实现&#xff0c;他们的关系就像MVC和SpringMVC、IOC与DI类似。 AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通过预…

CHAPTER 1 Zabbix介绍及安装

Zabbix介绍及安装1.1 Zabbix监控1 为什么要监控1.1 网站可用性2 监控什么东西2.1 监控范畴3 怎么来监控3.1 远程管理服务器3.2 监控硬件3.3 查看cpu相关3.4 内存3.5 磁盘3.6 监控网络4 监控工具总览5 zabbix介绍5.1 zabbix的组成5.2 zabbix监控范畴1.2 安装zabbix1 环境检查2 安…