数据结构与算法之字符串排列
字符串排列指的是将一个字符串中的所有字符按照一定顺序进行排列,使得得到一个新的字符串。例如,字符串"abc"的排列有"abc"、“acb”、“bac”、“bca”、“cab”、"cba"六种可能。
字符串排列的原理可以通过递归实现。假设输入的字符串为s,先将第一个字符和后面的字符依次交换位置,得到新字符串s’。接着将s’的第一个字符和剩下的字符进行交换,得到新字符串s’'。以此类推,直到交换到最后一个字符。
在实现字符串排列时,需要注意以下几点:
-
对于有重复字符的字符串,需要去重,避免出现重复排列。
-
递归实现时,需要在每一次交换后将原始字符串还原,以便进行下一次交换。
-
递归实现时,可以通过设置一个标志位记录当前字符是否已经交换过,避免重复交换。
以下是使用Java代码实现字符串排列的示例:
public ArrayList<String> permutation(String s) {
ArrayList<String> res = new ArrayList<>();
if (s == null || s.length() == 0) {
return res;
}
char[] chars = s.toCharArray();
permutation(chars, 0, res);
return res;
}
private void permutation(char[] chars, int i, ArrayList<String> res) {
if (i == chars.length - 1) {
res.add(new String(chars));
return;
}
for (int j = i; j < chars.length; j++) {
if (j == i || chars[j] != chars[i]) {
swap(chars, i, j);
permutation(chars, i + 1, res);
swap(chars, i, j);
}
}
}
private void swap(char[] chars, int i, int j) {
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
一、C 实现 字符串排列 及代码详解
字符串的排列指的是对字符串内部的字符进行排列组合,并输出所有可能的排列。例如,字符串 “abc” 的排列有 “abc”、“acb”、“bac”、“bca”、“cab” 和 “cba”。
以下是 C 语言实现字符串排列的代码及其详解:
#include <stdio.h>
#include <string.h>
void swap(char *a, char *b) {
char temp = *a;
*a = *b;
*b = temp;
}
void permute(char *str, int l, int r) {
if (l == r) {
printf("%s\n", str);
} else {
for (int i = l; i <= r; i++) {
swap(str + l, str + i);
permute(str, l + 1, r);
swap(str + l, str + i);
}
}
}
int main() {
char str[] = "abc";
int n = strlen(str);
permute(str, 0, n - 1);
return 0;
}
这个程序使用递归方法实现字符串排列。
-
swap()
函数用于交换两个字符的值。 -
permute()
函数接收三个参数:原始字符串str
、字符串的开始位置l
和字符串的结束位置r
。 -
如果
l
等于r
,则说明我们已经对字符串中的所有字符进行了一次排列,此时输出字符串。 -
如果
l
不等于r
,则将str[l]
和str[i]
交换,其中i
从l
开始,直到r
。 -
递归调用
permute()
函数,将l
增加1并保持r
不变。 -
再次交换
str[l]
和str[i]
,以便进行下一轮排列。 -
在 main() 函数中,首先定义字符串
str
,然后计算字符串的长度n
。 -
最后调用
permute()
函数,传递str
、开始位置0
和结束位置n-1
。
此时,程序将输出 “abc”、“acb”、“bac”、“bca”、“cab” 和 “cba”,因为这是 “abc” 的所有排列。
二、C++ 实现 字符串排列 及代码详解
字符串排列,即对给定的字符串中的字符进行排列,并输出所有排列的可能性。例如字符串"abc"的排列可能为"abc"、“acb”、“bac”、“bca”、“cab”、“cba”。
下面是一种使用C++语言实现字符串排列的方法:
- 从字符串的第一个字符开始,依次交换每个字符与其后面的字符;
- 对于每个交换后的字符串,递归地对其后面的字符进行交换;
- 当递归到最后一个字符时,将当前字符串输出。
具体实现代码如下:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void permutation(string str, int begin, vector<string>& result) {
if (begin == str.size() - 1) {
result.push_back(str);
return;
}
for (int i = begin; i < str.size(); ++i) {
swap(str[begin], str[i]);
permutation(str, begin + 1, result);
swap(str[begin], str[i]);
}
}
int main() {
string str = "abc";
vector<string> result;
permutation(str, 0, result);
for (auto s : result) {
cout << s << endl;
}
return 0;
}
首先,我们定义了一个permutation
函数,用来实现字符串排列。该函数以三个参数作为输入:字符串str
、当前要交换的字符位置begin
、保存排列结果的向量result
。
函数的主要实现如下:
- 当当前要交换的字符位置
begin
达到字符串的末尾时,说明已经完成了一次排列,将该字符串添加到result
中并返回。 - 对于当前字符串,从
begin
位置开始依次与后面的字符进行交换,并递归地对后面的字符进行交换,直到begin
达到字符串末尾。
在main
函数中,我们首先定义了要排列的字符串str
以及保存排列结果的向量result
。然后调用permutation
函数进行排列,并将结果输出。
三、Java 实现 字符串排列 及代码详解
字符串排列是指将一个字符串中的所有字符按照不同的排列方式进行组合,得到不同的字符串序列。实现字符串排列可以用回溯法或递归实现。下面是一个使用递归实现字符串排列的 Java 代码:
import java.util.*;
public class StringPermutation {
public static ArrayList<String> permutation(String str) {
ArrayList<String> result = new ArrayList<>();
if (str == null || str.length() == 0) {
return result;
}
char[] arr = str.toCharArray();
permutationHelper(arr, 0, result);
Collections.sort(result); // 对结果集进行排序
return result;
}
private static void permutationHelper(char[] arr, int index, ArrayList<String> result) {
if (index == arr.length - 1) {
result.add(new String(arr));
} else {
Set<Character> charSet = new HashSet<>(); // 用set保存当前已经排列过的字符,避免重复排列
for (int i = index; i < arr.length; i++) {
if (!charSet.contains(arr[i])) {
charSet.add(arr[i]);
swap(arr, index, i);
permutationHelper(arr, index + 1, result);
swap(arr, index, i);
}
}
}
}
private static void swap(char[] arr, int i, int j) {
if (i != j) {
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
代码详解:
permutation()
方法是主方法,接收一个字符串,返回一个排列好的字符串序列。- 首先对字符串进行判断,若字符串为 null 或长度为 0,则返回一个空的结果集。
- 将字符串转为字符数组,并调用
permutationHelper()
方法进行递归排列。 permutationHelper()
方法接收一个字符数组、一个索引和一个结果集,表示对字符数组从索引处开始排列得到的结果添加进结果集。- 如果索引已经到了字符数组的最后一个位置,则说明已经得到一个排列,将该排列加入结果集。
- 否则,从当前索引开始依次将字符数组中的元素与当前索引位置交换,并递归排列剩余的字符数组,直到得到所有排列。
- 用 set 来保存当前已经排列过的字符,避免重复排列。
- 最终返回排列好的结果集。