找出弦的所有排列的优雅方法是什么。例如,ba的排列,将是ba和ab,但更长的字符串,如abcdefgh?是否有Java实现示例?
当前回答
倒计时Quickperm算法的通用实现,表示#1(可伸缩,非递归)。
/**
* Generate permutations based on the
* Countdown <a href="http://quickperm.org/">Quickperm algorithm</>.
*/
public static <T> List<List<T>> generatePermutations(List<T> list) {
List<T> in = new ArrayList<>(list);
List<List<T>> out = new ArrayList<>(factorial(list.size()));
int n = list.size();
int[] p = new int[n +1];
for (int i = 0; i < p.length; i ++) {
p[i] = i;
}
int i = 0;
while (i < n) {
p[i]--;
int j = 0;
if (i % 2 != 0) { // odd?
j = p[i];
}
// swap
T iTmp = in.get(i);
in.set(i, in.get(j));
in.set(j, iTmp);
i = 1;
while (p[i] == 0){
p[i] = i;
i++;
}
out.add(new ArrayList<>(in));
}
return out;
}
private static int factorial(int num) {
int count = num;
while (num != 1) {
count *= --num;
}
return count;
}
它需要list,因为泛型不能很好地使用数组。
其他回答
改进的代码相同
static String permutationStr[];
static int indexStr = 0;
static int factorial (int i) {
if (i == 1)
return 1;
else
return i * factorial(i-1);
}
public static void permutation(String str) {
char strArr[] = str.toLowerCase().toCharArray();
java.util.Arrays.sort(strArr);
int count = 1, dr = 1;
for (int i = 0; i < strArr.length-1; i++){
if ( strArr[i] == strArr[i+1]) {
count++;
} else {
dr *= factorial(count);
count = 1;
}
}
dr *= factorial(count);
count = factorial(strArr.length) / dr;
permutationStr = new String[count];
permutation("", str);
for (String oneStr : permutationStr){
System.out.println(oneStr);
}
}
private static void permutation(String prefix, String str) {
int n = str.length();
if (n == 0) {
for (int i = 0; i < indexStr; i++){
if(permutationStr[i].equals(prefix))
return;
}
permutationStr[indexStr++] = prefix;
} else {
for (int i = 0; i < n; i++) {
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
}
}
}
我一直在学习递归思考,第一个打动我的自然解决方案如下。一个更简单的问题是找到一个短一个字母的字符串的排列。我将假设,并相信我的每一根纤维,我的函数可以正确地找到一个字符串的排列,比我目前正在尝试的字符串短一个字母。
Given a string say 'abc', break it into a subproblem of finding permutations of a string one character less which is 'bc'. Once we have permutations of 'bc' we need to know how to combine it with 'a' to get the permutations for 'abc'. This is the core of recursion. Use the solution of a subproblem to solve the current problem. By observation, we can see that inserting 'a' in all the positions of each of the permutations of 'bc' which are 'bc' and 'cb' will give us all the permutations of 'abc'. We have to insert 'a' between adjacent letters and at the front and end of each permutation. For example
我们有bc
“a”+“bc”=“abc”
“b”+“a”+“c”=“bac”
“b”+“a”=“b”
对于'cb'我们有
a + b = acb
“c”+“a”+“b”=“cab”
“cb”+“a”=“cb”
下面的代码片段将说明这一点。下面是该代码片段的工作链接。
def main():
result = []
for permutation in ['bc', 'cb']:
for i in range(len(permutation) + 1):
result.append(permutation[:i] + 'a' + permutation[i:])
return result
if __name__ == '__main__':
print(main())
完整的递归解将是。下面是完整代码的工作链接。
def permutations(s):
if len(s) == 1 or len(s) == 0:
return s
_permutations = []
for permutation in permutations(s[1:]):
for i in range(len(permutation) + 1):
_permutations.append(permutation[:i] + s[0] + permutation[i:])
return _permutations
def main(s):
print(permutations(s))
if __name__ == '__main__':
main('abc')
作为Python生成器,带有现代类型提示:
from typing import Iterator
def permutations(string: str, prefix: str = '') -> Iterator[str]:
if len(string) == 0:
yield prefix
for i, character in enumerate(string):
yield from permutations(string[:i] + string[i + 1:], prefix + character)
for p in permutations('abcd'):
print(p)
import java.io.*;
public class Anagram {
public static void main(String[] args) {
java.util.Scanner sc=new java.util.Scanner(System.in);
PrintWriter p=new PrintWriter(System.out,true);
p.println("Enter Word");
String a[],s="",st;boolean flag=true;
int in[],n,nf=1,i,j=0,k,m=0;
char l[];
st=sc.next();
p.println("Anagrams");
p.println("1 . "+st);
l=st.toCharArray();
n=st.length();
for(i=1;i<=n;i++){
nf*=i;
}
i=1;
a=new String[nf];
in=new int[n];
a[0]=st;
while(i<nf){
for(m=0;m<n;m++){
in[m]=n;
}j=0;
while(j<n){
k=(int)(n*Math.random());
for(m=0;m<=j;m++){
if(k==in[m]){
flag=false;
break;
}
}
if(flag==true){
in[j++]=k;
}flag=true;
}s="";
for(j=0;j<n;j++){
s+=l[in[j]];
}
//Removing same words
for(m=0;m<=i;m++){
if(s.equalsIgnoreCase(a[m])){
flag=false;
break;
}
}
if(flag==true){
a[i++]=s;
p.println(i+" . "+a[i-1]);
}flag=true;
}
}
}
这是一个C解:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
char* addLetter(char* string, char *c) {
char* result = malloc(sizeof(string) + 2);
strcpy(result, string);
strncat(result, c, 1);
return result;
}
char* removeLetter(char* string, char *c) {
char* result = malloc(sizeof(string));
int j = 0;
for (int i = 0; i < strlen(string); i++) {
if (string[i] != *c) {
result[j++] = string[i];
}
}
result[j] = '\0';
return result;
}
void makeAnagram(char *anagram, char *letters) {
if (*letters == '\0') {
printf("%s\n", anagram);
return;
}
char *c = letters;
while (*c != '\0') {
makeAnagram(addLetter(anagram, c),
removeLetter(letters, c));
c++;
}
}
int main() {
makeAnagram("", "computer");
return 0;
}
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap