[c++/java]递归系列

2023-10-27

本系列是根据个人的做题总结出来,或许有不对之处,望给位大佬指出。同时这个系列也是长期的一个系列,每遇到一个优秀的递归题目,我都会添加上去。

基本递归思路

递归之结束条件

个人认为在写递归之前应该首先考虑什么时候递归结束,或者是递归收敛于什么条件。这样既可以减少递归陷入死循环的几率,也能提供写递归的一个方向。这个条件通常为因为递归而不断变化的值。

递归之变化条件

递归算法通常会使某个值或者数组发生持续性的变化,而在写递归之前我们应该首先清楚这个值的变化有哪些可能。

递归之判断条件

这里的判断条件是针对于递归变化条件而考虑的,而通常来讲递归也往往发生在判断条件当中。

例题

八皇后

递归的经典题目,问题就不细说了

在进行分析前介绍一个八皇后的小技巧:

通常而言对于这种棋盘问题来说,首先要做的就是创建一个棋盘的初始化,一般的棋盘都是二维数组,但对于这道题来说设置一维数组即可,一维数组的默认值也就是下标值当作棋盘的行,数组的内容当作棋盘的列

int map[4] = {2,3,1};//分别指的是第一行第四列,第二行第三列,以此类推

首先是根据上文进行思路分析

int main(){
	check(1);
	return 0;
} 

1.递归之结束条件

八皇后的基本思路是依次安放每一行的皇后,当安放完最后一行时,即可结束递归

void check(int n){
	if(n == Max + 1){
		print();
		return;
	}
}

2.递归之变化条件

递归影响的是每一行皇后列所在的位置,即每一次递归完成后,皇后所在的列会发生变化,而我们的目的是取得所有满足的值,因此需要建立一个for循环,来使皇后的列发生改变

	for(int i = 1; i <= Max; i++){
		array[n] = i;
}

3.递归之判断条件

这里有两个判断条件:

    1.  第n个皇后是否和前面的n-1个皇后在同一列

    2.表示判断第n个皇后是否和第i皇后是否在同一斜线

基于如上考虑首先少不了一个for循环;

然后对于条件一,可以采用依次循环前面数组的值来判断;

而对于条件二可以在坐标中想:

首先 i,n 代表横坐标,array[i],array[n]代表纵坐标,只要两者形成的斜率的绝对值不等于1,那么就满足,可以结合下面代码来看

	for(int i = 1; i <= Max; i++){
		array[n] = i;
		if(juge(n)){
			check(n+1);
		}
	} 
bool juge(int n){
	for(int i = 1; i < n; i++){
		if(array[i] == array[n] || abs(n - i) == abs(array[n] - array[i])){
			return false;
		}
	}
	return true;
}

完整代码

c++

#include<iostream>
#include<stdlib.h>
using namespace std;
const int N = 10;
int Max = 8;
int array[N];
void print(){
	for(int i = 1; i <= Max; i++){
		cout<<array[i]<<" ";
	} 
	cout<<endl;
}
bool juge(int n){
	for(int i = 1; i < n; i++){
		if(array[i] == array[n] || abs(n - i) == abs(array[n] - array[i])){
			return false;
		}
	}
	return true;
}
void check(int n){
	if(n == Max + 1){
		print();
		return;
	}
	for(int i = 1; i <= Max; i++){
		array[n] = i;
		if(juge(n)){
			check(n+1);
		}
	} 
}
int main(){
	check(1);
	return 0;
} 

 java

public class Queue8 {

	//定义一个max表示共有多少个皇后
	int max = 8;
	//定义数组array, 保存皇后放置位置的结果,比如 arr = {0 , 4, 7, 5, 2, 6, 1, 3} 
	int[] array = new int[max];
	static int count = 0;
	static int judgeCount = 0;
	public static void main(String[] args) {
		//测试一把 , 8皇后是否正确
		Queue8 queue8 = new Queue8();
		queue8.check(0);
		System.out.printf("一共有%d解法", count);
		System.out.printf("一共判断冲突的次数%d次", judgeCount); // 1.5w
		
	}
	
	
	
	//编写一个方法,放置第n个皇后
	//特别注意: check 是 每一次递归时,进入到check中都有  for(int i = 0; i < max; i++),因此会有回溯
	private void check(int n) {
		if(n == max) {  //n = 8 , 其实8个皇后就既然放好
			print();
			return;
		}
		
		//依次放入皇后,并判断是否冲突
		for(int i = 0; i < max; i++) {
			//先把当前这个皇后 n , 放到该行的第1列
			array[n] = i;
			//判断当放置第n个皇后到i列时,是否冲突
			if(judge(n)) { // 不冲突
				//接着放n+1个皇后,即开始递归
				check(n+1); //  
			}
			//如果冲突,就继续执行 array[n] = i; 即将第n个皇后,放置在本行得 后移的一个位置
		}
	}
	
	//查看当我们放置第n个皇后, 就去检测该皇后是否和前面已经摆放的皇后冲突
	private boolean judge(int n) {
		judgeCount++;
		for(int i = 0; i < n; i++) {
			if(array[i] == array[n] || Math.abs(n-i) == Math.abs(array[n] - array[i]) ) {
				return false;
			}
		}
		return true;
	}
	
	//写一个方法,可以将皇后摆放的位置输出
	private void print() {
		count++;
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " ");
		}
		System.out.println();
	}

}

反转链表

反转链表

题目

定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点

数据范围

链表长度 [0,30]。 

样例

输入:1->2->3->4->5->NULL

输出:5->4->3->2->1->NULL

 思路

首先基本的思路是,将旧链表反转到一个新的链表中,并且最后旧链表为空

结束条件

当旧链表为空时结束递归

变化条件

链表中每个节点指向会随着递归发生变化

判断条件

这里不需要

特殊条件

因为链表发生了反转,就需要一个节点指向旧链表的尾节点,这里就是使用递归的方式遍历到了旧链表的尾节点

c++/递归

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next) return head;
        ListNode *tail = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return tail;
    }
};

java/非递归

public static void reverse(HeroNode head){
    if(head.next == null || head.next.next == null){
        return;
    }
    HeroNode cur = head.next;
    HeroNode next = null;//指向cur的下一个节点
    HeroNode reversehead = new HeroNode(0, "", "");
    while(cur!= null){
        next = cur.next;//先将cur的下一个节点保存下来
        cur.next = reversehead.next;//将cur的下一个节点指向新的链表的最前端
        reversehead.next = cur;//将cur链接到新的链表上
        cur = next;
    }
    head.next = reversehead.next;
}

=========================================================================

接下来的几道题都是着重于处理递归的变化条件

递归实现指数型枚举

题目:

从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。

输入格式:

输入一个整数 n

输出格式:

每行输出一种方案。

同一行内的数必须升序排列,相邻两个数用恰好 11 个空格隔开。

对于没有选任何数的方案,输出空行。

本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。

数据范围

1≤n≤15 

输入样例

输出样例


3
2
2 3
1
1 3
1 2
1 2 3

 代码:

#include <iostream>
using namespace std;

int n;
bool vis[20];
// u是当前枚举到的数,state是二进制数记录哪些数被选
void dfs(int u, int state) {
    if (u == n) {
        for (int i = 0; i < n; i ++)
            if (state >> i & 1)
                cout << i + 1 << " ";
            cout << endl;
        return ;
    }

    dfs (u + 1, state);  // 不用u这个数
    dfs (u + 1, state | (1 << u)); // 用u这个数
}

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

[c++/java]递归系列 的相关文章

  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐

  • 21、同步与异步(三种方法)

    1 同步 按顺序一条一条数据执行 1 同步 按顺序一条一条数据执行 console log 第1条数据 console log 第2条数据 console log 第3条数据 console log 第4条数据 console log 第5
  • flowable工作流简介

    官网地址 https www flowable org Flowable6 3中文教程 https tkjohn github io flowable userguide introduction Flowable Modeler 流程定义
  • 数据结构-树(树基本实现C++)

    树形结构是一种重要的非线性数据结构 其中树和二叉树最为常用 直观看来树是以分支关系定义的层次结构 树形结构是我们平时比较熟悉的 比如文件夹目录 公司组织关系等 在计算机领域也得到广泛的应用 编译程序就是以树来表示源程序的语法结构 二叉树是一
  • osgEarth的Rex引擎原理分析(一二六)rex瓦片组织方式

    目标 一二五 中问题212 通过如下确定瓦片的组织方式 核心是profile osgEarth Map cpp void Map calculateProfile collect the terrain layers we will nee
  • [1075]OpenSSL和Python实现RSA Key公钥加密私钥解密

    文章目录 1 OpenSSL实现非对称加解密 1 1 生成私钥 并导出公钥 1 2 准备测试数据 1 3 公钥加密 1 4 私钥解密 2 Python实现非对称加解密 3 非对称加解密的疑问 为什么RSA公钥每次加密得到的结果都不一样 1
  • Linux复制到home后自动删除,[rm] Linux 防止"rm -rf /" 误删除

    引以为戒 一 缘由 最近看到这则新闻 很是悲伤 因为我最近也在用ansible 然而这一错误源自Ansible上糟糕的代码设计 这款Linux实用工具被用于在多台不同服务器上自动执行脚本 开发者解释到 实际参数应该是 rm rf foo b
  • Tomcat部署静态页面

    安装Tomcat 1 将html文件放在ROOT文件下 2 将html文件直接放在webapp下
  • java并发包:读写锁

    本文转载至 http blog csdn net a910626 article details 51900954 ReadWriteLock是jdk5中提供的读写分离锁 读写分离锁可以有效的帮助减少锁竞争 以提升性能 用锁分离的机制来提升
  • 手机设置代理后无法上网_fiddler 手机代理设置过程及问题解决

    之前在学习用fiddler对手机进行抓包的时候 手机设置代理一直失败 电脑ip地址和端口号也是正确的 但就是发生一些奇奇怪怪的问题连接不上 但最后把所有过程重新试了一遍就莫名其妙的成功了 在这里设置代理的整个过程梳理一下 如果看到这篇文章的
  • Unity ILRuntime Debugger使用及常见问题

    目录 前言 1 安装 2 使用 3 常见问题 前言 ILRuntime支持在VS中断点调试 下面说一下ILRuntime Debugger的使用及常见问题 1 安装 需要下载对应版本的ILRuntime Debugger VS插件 我是在U
  • [Oracle][Postgresql][mysql]三个数据库产品下表字段存在空值或者为空创建索引是否生效测试

    postgresql 数据库测试开始 本次测试以pg 数据库 10 11版本 postgres select version version PostgreSQL 10 11 compiled by Visual C build 1800
  • BIO测试例子

    BIO一个测试例子 运行的环境window 运行的环境window bio的模式 当前有一个客户端在访问服务端时 并且阻塞在发送数据处 第二个客户端是无法访问的 import java io IOException import java
  • 用好lua+unity,让性能飞起来——lua与c#交互篇

    前言 在看了uwa之前发布的 Unity项目常见Lua解决方案性能比较 决定动手写一篇关于lua unity方案的性能优化文 整合lua是目前最强大的unity热更新方案 毕竟这是唯一可以支持ios热更新的办法 然而作为一个重度ulua用户
  • openwrt安装打印机服务器_原创

    作者 水滴实验室 单位 恒安嘉新 前言 随着物联网时代逐步的发展 设备之间的联系更为紧密 每个节点都无法独立存在 而与我们每个人都 息息相关的一些设备 路由器 摄像头 打印机等越来越多的影响着我们的生活各个方面 小到个人隐 私 大到敌对势力
  • 如何在Linux下配置网络访问外网

    Linux下的网络配置 1 查看自己的网卡编号 2 设置使用的网卡 IP地址 网关等参数 3 设置DNS服务器 4 重启网络服务 5 测试是否能ping通外网 6 无法Ping通的异常处理 7 Ping 外网的时候提示Temporary f
  • 鸿蒙3.0应用开发体验

    鸿蒙os3 0发布以来 华为官方开始主推ets arkui开发模式 逐渐抛弃java 为以后去安卓化做铺垫 但目前在笔者体验来看 仍需要大力完善 还有很长的路要走 什么是ets ts是js的超集 而ets是ts的超集 ets后缀的文件中可以
  • Django 迁移数据、迁移服务

    本文介绍两种常用的 Django 服务迁移数据方法 这两种方法都需要在新的服务器部署好数据库 创建好相应的数据库表和用户以后再进行 1 使用dumpdata命令 针对数据量不是很大的项目 可以使用此方法 操作起来比较简单 1 1 数据导出
  • 简单了解IPv4编址

    目录 一 IPv4地址 二 进制转换 三 有类IPv4 四 无类IPv4 4 1 子网掩码 4 2 地址规划 4 3 VLSM可变长子网掩码 五 私有IPv4地址 六 IPv4报文格式 七 IP地址解析 一 IPv4地址 IPv4地址由 网
  • Vue2项目中使用高德地图自定义(Marker)标记点和创建(MassMarks)海量标记点

    前言 本篇文章就是单独分享一下在Vue2项目中如何自定义创建marker标记点和针对要创建庞大数量标记点时所采用的API 能够快速创建数量庞大的marker 不至于在浏览器渲染时产生卡顿的现象 需要了解如何在Vue2项目中引入高德地图请参照
  • [c++/java]递归系列

    本系列是根据个人的做题总结出来 或许有不对之处 望给位大佬指出 同时这个系列也是长期的一个系列 每遇到一个优秀的递归题目 我都会添加上去 基本递归思路 递归之结束条件 个人认为在写递归之前应该首先考虑什么时候递归结束 或者是递归收敛于什么条