打印不重复的字符串全排列(递归)

简介: 本文将详细解析在生成不重复的字符串全排列时使用的Java代码。首先,我们将展示一个常规的全排列生成方法,然后介绍如何通过使用HashSet来跳过已经尝试过的字符,从而避免生成重复的全排列。最后,我们提供了一道相关的编程题目以供练习。

      什么是不重复的字符串全排列?对于序列acc,它的全排列为accacccacccaccacac,其中acccca各出现两次。为了解决这个问题,我们需要找到一种方法,能够在生成全排列的过程中,避免产生重复的排列。


如果是普通字符串全排列,那么


输入:


acc


输出:


acc

acc

cac

cca

cca

cac


要求写出的去重的,也就是会输出:


acc

cac

cca


上代码进行比较吧,后面给出练习例题。


      首先,我们有一个方法用于生成序列的全排列。然后,我们有一个方法用于交换序列中的两个元素。我们将使用这两个方法来生成序列的全排列,并通过适当的方式避免产生重复的结果。

importjava.io.BufferedInputStream;
importjava.util.HashSet;
importjava.util.Scanner;
importjava.util.Set;
publicclasstest {
publicstaticvoidarrange1(char[] str, inti) {
if (i==str.length) {
System.out.println(str);
        } else {
for (intj=i; j<str.length; ++j) {
swap(str, i, j);
arrange1(str, i+1);
swap(str, i, j);
            }
        }
    }
publicstaticvoidarrange2(char[] str, inti) {
if (i==str.length) {
System.out.println(str);
        } else {
Set<Character>set=newHashSet<Character>(); // 每一层对应一个setfor (intj=i ; j<str.length; ++j) {
if (!set.contains(str[j])) { // 最上面一层的串是起始串,根据起始串思考set.add(str[j]);
swap(str, i, j);
arrange2(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();
arrange1(str.toCharArray(), 0);
System.out.println("======================");
arrange2(str.toCharArray(), 0);
cin.close();
    }
}

image.gif

      对于方法arrange1,它是一个普通的全排列生成方法,不会避免产生重复的结果。而方法arrange2则使用了一种新的方式,来避免产生重复的结果。在arrange2中,我们使用了一个HashSet来存储已经尝试过的字符。这样,如果我们碰到一个已经尝试过的字符,我们就可以直接跳过,而不需要再次生成以这个字符开始的全排列。这样,我们就可以避免产生重复的全排列。


相关题目:

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。


输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

题目链接:字符串的排列_牛客题霸_牛客网

测试用例会有空串"",此时不添加进集合,还会有"aa"


分析思路(盗图一张):


image.gif


AC代码:

importjava.util.ArrayList;
importjava.util.Set;
importjava.util.HashSet;
importjava.util.Collections;
importjava.util.Comparator;
publicclassSolution {
ArrayList<String>list=newArrayList<String>();
publicArrayList<String>Permutation(Stringstr) {
if (str.length() !=0) {
Arrange(str.toCharArray(), 0);
// 升序可以不用第二个参数,这里cab测试用例在cba前面,说明得排序,我个人觉得是题目有问题,排序偏离了出题人的意图Collections.sort(list, newComparator<String>(){
publicintcompare(Strings1, Strings2) {
returns1.compareTo(s2);
                }
            });
        }
returnlist;
    }
privatevoidArrange(char[] arr, inti) {
if (i==arr.length) {
list.add(newString(arr));
        } else {
Set<Character>set=newHashSet<Character>();
for (intj=i; j<arr.length; ++j) {
if (!set.contains(arr[j])) {
set.add(arr[j]);
if (i!=j) {
swap(arr, i, j);
                    }
Arrange(arr, i+1);
if (i!=j) {
swap(arr, i, j);
                    }
                }
            }
        }
    }
privatevoidswap(char[] arr, inti, intj) {
chartemp=arr[i];
arr[i] =arr[j];
arr[j] =temp;
    }
}

image.gif

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

目录
相关文章
|
1月前
使用 for 循环逆向输出数组
【10月更文挑战第29天】使用 for 循环逆向输出数组。
27 2
|
1月前
使用 for 循环输出数组
【10月更文挑战第29天】使用 for 循环输出数组。
28 3
|
3月前
|
C语言 索引 Python
利用递归函数调用方式,将所输入的5个字符,以相反顺序打印出来。
利用递归函数调用方式,将所输入的5个字符,以相反顺序打印出来。
99 4
|
5月前
|
语音技术
语音识别-----列表的常用操作课后练习讲解,用变量追加,取出第一个,取出最后一个,下标位置,列表的循环遍历,下标+1的写法,len下标可以小于这个值,while循环对index循环的遍历
语音识别-----列表的常用操作课后练习讲解,用变量追加,取出第一个,取出最后一个,下标位置,列表的循环遍历,下标+1的写法,len下标可以小于这个值,while循环对index循环的遍历
|
7月前
|
Java 大数据 数据处理
获取到数据循环写文件
这段代码是一个Java方法,用于分批处理数据。它定义了初始值和每批处理的数量,然后通过`PageInfo`对象获取数据。如果总数小于1,则直接返回空列表。否则,循环处理数据,防止环境中的多次空跳过,并在处理完一批数据后更新页码。代码中还提到,这个过程可以用于减少大数据操作带来的风险。此外,配有一张动图,可能表示数据处理的过程。
50 1
|
7月前
|
存储 搜索推荐 Serverless
用指针和动态内存分配的方法输入10,2,30, 4,5,按输入顺序逆置排序,输出排序后的元素,即输出5,4,30,2,10
用指针和动态内存分配的方法输入10,2,30, 4,5,按输入顺序逆置排序,输出排序后的元素,即输出5,4,30,2,10
50 0
|
算法
【递归可以干什么】1#重复执行某种模式
【递归可以干什么】1#重复执行某种模式
89 0
算法学习--递归打印*到*的数
算法学习--递归打印*到*的数
|
存储 算法
打印N个数的循环算法和递归算法比较
打印N个数的循环算法和递归算法比较
|
算法
算法 | 妙用递归(顺序&逆序)打印一个数的每一位
- 程序调用自身的编程技巧称为递归( recursion)。递归作为一种算法在程序设计语言中广泛应用 - 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问-题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量 - 递归的能力在于用有限的语句来定义对象的无限集合 - 一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回
268 0
算法 | 妙用递归(顺序&逆序)打印一个数的每一位