字符串全排列(递归)

简介: 字符串全排列,递归的应用

在日常编程中,字符串全排列是一种常见的问题,可以被应用于各种领域,比如密码破解、组合优化等等。在这篇博客中,我们将用Java语言来实现一个字符串全排列的解法,并通过递归方法来理解这个问题的本质。


题目:打印一个字符串的全部排列


比如:



假设我们有一个字符串,比如"abc",我们的目标是生成并打印出这个字符串的所有可能排列。

这个问题可以通过递归的方式来解决。具体的代码如下:


importjava.io.BufferedInputStream;
importjava.util.Scanner;
publicclasstest {
publicstaticvoidarrange(char[] str, inti) {
if (i==str.length) {
System.out.println(str);
        } else {
for (intj=i; j<str.length; ++j) {
swap(str, i, j); // 交换下标为i,j的字符arrange(str, i+1); // 对子串进行全排列swap(str, i, j); // 再换回来,保持原有序列            }
        }
    }
publicstaticvoidswap(char[] str, inti, intj) {
charc=str[i];
str[i] =str[j];
str[j] =c;
    }
publicstaticvoidmain(String[] args) {
Scannercin=newScanner(newBufferedInputStream(System.in));
Stringstr=cin.next();
arrange(str.toCharArray(), 0);
cin.close();
    }
}

image.gif

代码解读

      在我们的代码中,有两个核心的函数,一个是arrange(),用来进行递归排列,另一个是swap(),用来交换两个字符。

      首先,让我们看一下arrange()这个函数。

      这个函数的参数包括一个字符数组str和一个索引istr就是我们需要排列的字符串,而i则是我们当前处理到的字符的索引。

      在函数的主体中,我们首先检查i是否等于字符串的长度。如果是,那么我们就找到了一个可能的排列,可以直接将其打印出来。如果不是,那么我们需要对从i开始到字符串结尾的每一个字符,分别与i位置的字符进行交换,然后对剩下的字符串进行全排列。

      这就是递归的核心思想:我们首先解决问题的一部分(即,确定字符串的前i个字符),然后用同样的方法解决剩下的问题(即,对剩下的字符串进行全排列)。

然后,让我们看一下swap()这个函数。

      这个函数的参数是一个字符数组和两个索引ij。这个函数的作用就是将ij位置的字符交换。

      这个函数在arrange()中起着关键的作用。在确定了字符串的前i个字符后,我们需要将剩下的字符进行全排列。为了实现这一点,我们将剩下的每一个字符依次与第i个字符交换,然后对剩下的字符串进行全排列。在这个过程结束后,我们再将字符换回来,以保证在下一次循环中,字符串的前i个字符仍然是确定的。

      通过这种方式,我们可以保证我们生成的所有排列都是不同的,因为在每一步,我们都是在前i个字符确定的情况下,对剩下的字符进行全排列。

      总结起来,这段代码使用了递归和回溯的思想,通过不断地交换字符和递归调用自身,实现了字符串的全排列。

================================Talk is cheap, show me the code===============================

目录
相关文章
|
前端开发 Java 关系型数据库
【Mybatis-Plus】mybatisplus更新时,实体字段为空,数据库不更新的解决方案
【Mybatis-Plus】mybatisplus更新时,实体字段为空,数据库不更新的解决方案
1852 0
|
消息中间件 NoSQL 数据库
一文讲透消息队列RocketMQ实现消费幂等
这篇文章,我们聊聊消息队列中非常重要的最佳实践之一:消费幂等。
一文讲透消息队列RocketMQ实现消费幂等
|
6月前
|
缓存 负载均衡 安全
Nginx 反向代理:原理、优势与配置指南
Nginx反向代理是核心服务器架构技术,可实现请求转发、负载均衡、高可用与安全防护。它隐藏后端服务器,自动剔除故障节点,并支持SSL终止、缓存等高级功能,配置简洁灵活,广泛应用于高性能Web系统。
629 13
|
数据采集 人工智能 编解码
2025年颠覆闭源大模型?MonkeyOCR:这款开源AI文档解析模型,精度更高,速度更快!
还在依赖昂贵且慢的闭源OCR工具?华中科技大学开源的MonkeyOCR文档解析模型,以其超越GPT4o的精度和更快的推理速度,在单机单卡(3090)上即可部署,正颠覆业界认知。本文将深入解析其设计哲学、核心突破——大规模自建数据集,并分享实测体验与避坑指南。
2682 87
|
Kubernetes 调度 虚拟化
Kubernetes和Docker有什么区别
【10月更文挑战第18天】Kubernetes和Docker有什么区别
|
存储 算法 Java
JvM JDK JRE 三者区别与联系详解
本文深入解析了Java编程中的三个核心概念:JVM(Java虚拟机)、JDK(Java开发工具包)和JRE(Java运行环境)。JVM是执行Java字节码的虚拟计算机,实现“一次编译,到处运行”;JDK包含JRE及开发工具,用于编写和调试Java程序;JRE负责运行已编译的Java程序。文章详细阐述了它们的功能、组成及应用场景,并通过实例说明其在实际开发中的作用,帮助开发者理解三者联系与区别,提升开发效率与问题解决能力。适合Java初学者及进阶开发者学习参考。
1730 3
|
JSON NoSQL MongoDB
Compass
【6月更文挑战第8天】Compass
727 9
|
算法 iOS开发 C++
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); 的作用和注意事项
默认情况下,C++的输入输出流与C标准库的输入输出函数是同步的,这会造成一定的性能损失。:使用cin.tie(0)和cout.tie(0)可以取消cin与cout之间的绑定,这意味着在进行输入操作时,不需要强行刷新输出缓冲区。:如果你的程序在输入输出中同时使用了C++的输入输出流和C标准库的输入输出函数(如scanf和printf),则不应该使用这段代码。:在使用了这段代码后,应避免使用C标准库的输入输出函数(如printf和scanf),因为这些函数与输入输出流的同步已被关闭。这段代码的主要用途是。
2253 1
|
UED
使echarts图例legend只选中一个(selectedMode)
本文介绍了如何在ECharts图表中设置图例(legend)的选中模式为单选('single'),以确保在有多个图例时,用户只能选择一个图例项进行展示,从而提升图表的可读性和用户体验。
1807 2
使echarts图例legend只选中一个(selectedMode)