เป็นวิธีที่สง่าในการค้นหาพีชคณิตทั้งหมดของสตริงอะไร เช่นการเรียงสับเปลี่ยนสำหรับba
จะเป็นba
และab
แต่สิ่งที่เกี่ยวกับสตริงอีกต่อไปเช่นabcdefgh
? มีตัวอย่างการติดตั้ง Java หรือไม่?
เป็นวิธีที่สง่าในการค้นหาพีชคณิตทั้งหมดของสตริงอะไร เช่นการเรียงสับเปลี่ยนสำหรับba
จะเป็นba
และab
แต่สิ่งที่เกี่ยวกับสตริงอีกต่อไปเช่นabcdefgh
? มีตัวอย่างการติดตั้ง Java หรือไม่?
คำตอบ:
public static void permutation(String str) {
permutation("", str);
}
private static void permutation(String prefix, String str) {
int n = str.length();
if (n == 0) System.out.println(prefix);
else {
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
n==0
คุณสามารถหยุดระดับก่อนหน้านี้ที่และพิมพ์ออกมาn==1
prefix + str
ใช้การเรียกซ้ำ
นี่คือทางออกของฉันที่มีพื้นฐานมาจากความคิดของหนังสือ "ถอดรหัสการสัมภาษณ์การเข้ารหัส" (P54):
/**
* List permutations of a string.
*
* @param s the input string
* @return the list of permutations
*/
public static ArrayList<String> permutation(String s) {
// The result
ArrayList<String> res = new ArrayList<String>();
// If input string's length is 1, return {s}
if (s.length() == 1) {
res.add(s);
} else if (s.length() > 1) {
int lastIndex = s.length() - 1;
// Find out the last character
String last = s.substring(lastIndex);
// Rest of the string
String rest = s.substring(0, lastIndex);
// Perform permutation on the rest string and
// merge with the last character
res = merge(permutation(rest), last);
}
return res;
}
/**
* @param list a result of permutation, e.g. {"ab", "ba"}
* @param c the last character
* @return a merged new list, e.g. {"cab", "acb" ... }
*/
public static ArrayList<String> merge(ArrayList<String> list, String c) {
ArrayList<String> res = new ArrayList<>();
// Loop through all the string in the list
for (String s : list) {
// For each string, insert the last character to all possible positions
// and add them to the new list
for (int i = 0; i <= s.length(); ++i) {
String ps = new StringBuffer(s).insert(i, c).toString();
res.add(ps);
}
}
return res;
}
กำลังเรียกใช้เอาต์พุตของสตริง "abcd":
ขั้นตอนที่ 1: ผสาน [a] และ b: [ba, ab]
ขั้นตอนที่ 2: ผสาน [ba, ab] และ c: [cba, bca, bac, cab, acb, abc]
ขั้นตอนที่ 3: รวม [cba, bca, bac, cab, acb, abc] และ d: [dcba, cdba, cbda, cbad, dbca, bdca, bcda, bcad, dbac, bdac, badc, dcab, Cadb , cabd, dacb, adcb, acdb, acbd, dabc, adbc, abdc, abcd]
จากโซลูชันทั้งหมดที่ได้รับจากที่นี่และในฟอรัมอื่นฉันชอบ Mark Byers มากที่สุด คำอธิบายนั้นทำให้ฉันคิดและรหัสด้วยตัวเอง น่าเสียดายที่ฉันไม่สามารถลงคะแนนโซลูชันของเขาในขณะที่ฉันเป็นมือใหม่
อย่างไรก็ตามนี่คือการใช้คำอธิบายของเขา
public class PermTest {
public static void main(String[] args) throws Exception {
String str = "abcdef";
StringBuffer strBuf = new StringBuffer(str);
doPerm(strBuf,0);
}
private static void doPerm(StringBuffer str, int index){
if(index == str.length())
System.out.println(str);
else { //recursively solve this by placing all other chars at current first pos
doPerm(str, index+1);
for (int i = index+1; i < str.length(); i++) {//start swapping all other chars with current first char
swap(str,index, i);
doPerm(str, index+1);
swap(str,i, index);//restore back my string buffer
}
}
}
private static void swap(StringBuffer str, int pos1, int pos2){
char t1 = str.charAt(pos1);
str.setCharAt(pos1, str.charAt(pos2));
str.setCharAt(pos2, t1);
}
}
ฉันชอบโซลูชันนี้ก่อนหนึ่งในเธรดนี้เนื่องจากโซลูชันนี้ใช้ StringBuffer ฉันจะไม่พูดว่าโซลูชันของฉันไม่ได้สร้างสตริงชั่วคราวใด ๆ (จริง ๆ แล้วมันจะทำในsystem.out.println
ที่toString()
ของ StringBuffer เรียกว่า) แต่ฉันแค่รู้สึกว่านี่ดีกว่าวิธีแรกที่สร้างสตริงตัวอักษรมากเกินไป อาจเป็นนักแสดงบางคนที่มีประสิทธิภาพสามารถประเมินสิ่งนี้ในแง่ของ 'หน่วยความจำ' (สำหรับ 'เวลา' มันล่าช้าแล้วเนื่องจากการ 'สลับ' พิเศษนั้น)
if(index == str.length())
และเพียงdoPerm(str, index + 1);
? currPos
ดูเหมือนว่าไม่จำเป็นที่นี่
โซลูชันพื้นฐานมากใน Java คือใช้การเรียกซ้ำ + Set (เพื่อหลีกเลี่ยงการทำซ้ำ) หากคุณต้องการจัดเก็บและส่งคืนสตริงโซลูชัน:
public static Set<String> generatePerm(String input)
{
Set<String> set = new HashSet<String>();
if (input == "")
return set;
Character a = input.charAt(0);
if (input.length() > 1)
{
input = input.substring(1);
Set<String> permSet = generatePerm(input);
for (String x : permSet)
{
for (int i = 0; i <= x.length(); i++)
{
set.add(x.substring(0, i) + a + x.substring(i));
}
}
}
else
{
set.add(a + "");
}
return set;
}
ผู้มีส่วนร่วมก่อนหน้าทั้งหมดได้ทำงานที่ยอดเยี่ยมในการอธิบายและให้รหัส ฉันคิดว่าฉันควรแบ่งปันวิธีการนี้เช่นกันเพราะอาจช่วยคนได้ การแก้ปัญหาขึ้นอยู่กับ ( อัลกอริทึมของฮีป )
สองสิ่ง:
สังเกตุรายการสุดท้ายที่ปรากฎใน excel เป็นเพียงการช่วยให้คุณเห็นภาพตรรกะได้ดีขึ้น ดังนั้นค่าจริงในคอลัมน์สุดท้ายจะเป็น 2,1,0 (ถ้าเราต้องเรียกใช้รหัสเพราะเรากำลังจัดการกับอาร์เรย์และอาร์เรย์เริ่มต้นด้วย 0)
อัลกอริทึมการแลกเปลี่ยนเกิดขึ้นตามค่าคู่หรือคี่ของตำแหน่งปัจจุบัน มันอธิบายตัวเองได้ดีมากหากคุณดูว่าวิธีการแลกเปลี่ยนนั้นถูกเรียกใช้ที่ใดคุณจะเห็นว่าเกิดอะไรขึ้น
นี่คือสิ่งที่เกิดขึ้น:
public static void main(String[] args) {
String ourword = "abc";
String[] ourArray = ourword.split("");
permute(ourArray, ourArray.length);
}
private static void swap(String[] ourarray, int right, int left) {
String temp = ourarray[right];
ourarray[right] = ourarray[left];
ourarray[left] = temp;
}
public static void permute(String[] ourArray, int currentPosition) {
if (currentPosition == 1) {
System.out.println(Arrays.toString(ourArray));
} else {
for (int i = 0; i < currentPosition; i++) {
// subtract one from the last position (here is where you are
// selecting the the next last item
permute(ourArray, currentPosition - 1);
// if it's odd position
if (currentPosition % 2 == 1) {
swap(ourArray, 0, currentPosition - 1);
} else {
swap(ourArray, i, currentPosition - 1);
}
}
}
}
อันนี้ไม่มีการเรียกซ้ำ
public static void permute(String s) {
if(null==s || s.isEmpty()) {
return;
}
// List containing words formed in each iteration
List<String> strings = new LinkedList<String>();
strings.add(String.valueOf(s.charAt(0))); // add the first element to the list
// Temp list that holds the set of strings for
// appending the current character to all position in each word in the original list
List<String> tempList = new LinkedList<String>();
for(int i=1; i< s.length(); i++) {
for(int j=0; j<strings.size(); j++) {
tempList.addAll(merge(s.charAt(i), strings.get(j)));
}
strings.removeAll(strings);
strings.addAll(tempList);
tempList.removeAll(tempList);
}
for(int i=0; i<strings.size(); i++) {
System.out.println(strings.get(i));
}
}
/**
* helper method that appends the given character at each position in the given string
* and returns a set of such modified strings
* - set removes duplicates if any(in case a character is repeated)
*/
private static Set<String> merge(Character c, String s) {
if(s==null || s.isEmpty()) {
return null;
}
int len = s.length();
StringBuilder sb = new StringBuilder();
Set<String> list = new HashSet<String>();
for(int i=0; i<= len; i++) {
sb = new StringBuilder();
sb.append(s.substring(0, i) + c + s.substring(i, len));
list.add(sb.toString());
}
return list;
}
System.out.println(permute("AABBC").size());
แสดง 45 แต่จริง ๆ แล้ว 5! = 120
ลองใช้อินพุตabc
เป็นตัวอย่าง
เริ่มต้นด้วยองค์ประกอบสุดท้าย ( c
) ในชุด ( ["c"]
) จากนั้นเพิ่มองค์ประกอบสุดท้ายที่สอง ( b
) ไปยังด้านหน้าส่วนท้ายและตำแหน่งที่เป็นไปได้ทั้งหมดที่อยู่ตรงกลางทำให้มัน["bc", "cb"]
เป็นแบบเดียวกันกับที่มันจะเพิ่มองค์ประกอบถัดไป จากด้านหลัง ( a
) ไปยังแต่ละสตริงในชุดทำให้:
"a" + "bc" = ["abc", "bac", "bca"] and "a" + "cb" = ["acb" ,"cab", "cba"]
ดังนั้นการเปลี่ยนแปลงทั้งหมด:
["abc", "bac", "bca","acb" ,"cab", "cba"]
รหัส:
public class Test
{
static Set<String> permutations;
static Set<String> result = new HashSet<String>();
public static Set<String> permutation(String string) {
permutations = new HashSet<String>();
int n = string.length();
for (int i = n - 1; i >= 0; i--)
{
shuffle(string.charAt(i));
}
return permutations;
}
private static void shuffle(char c) {
if (permutations.size() == 0) {
permutations.add(String.valueOf(c));
} else {
Iterator<String> it = permutations.iterator();
for (int i = 0; i < permutations.size(); i++) {
String temp1;
for (; it.hasNext();) {
temp1 = it.next();
for (int k = 0; k < temp1.length() + 1; k += 1) {
StringBuilder sb = new StringBuilder(temp1);
sb.insert(k, c);
result.add(sb.toString());
}
}
}
permutations = result;
//'result' has to be refreshed so that in next run it doesn't contain stale values.
result = new HashSet<String>();
}
}
public static void main(String[] args) {
Set<String> result = permutation("abc");
System.out.println("\nThere are total of " + result.size() + " permutations:");
Iterator<String> it = result.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
ทีนี้นี่คือทางออก O (n!) ที่สง่างามและไม่เกิดซ้ำ:
public static StringBuilder[] permutations(String s) {
if (s.length() == 0)
return null;
int length = fact(s.length());
StringBuilder[] sb = new StringBuilder[length];
for (int i = 0; i < length; i++) {
sb[i] = new StringBuilder();
}
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
int times = length / (i + 1);
for (int j = 0; j < times; j++) {
for (int k = 0; k < length / times; k++) {
sb[j * length / times + k].insert(k, ch);
}
}
}
return sb;
}
หนึ่งในวิธีการแก้ปัญหาง่ายๆคือการสลับอักขระซ้ำโดยใช้พอยน์เตอร์สองตัว
public static void main(String[] args)
{
String str="abcdefgh";
perm(str);
}
public static void perm(String str)
{ char[] char_arr=str.toCharArray();
helper(char_arr,0);
}
public static void helper(char[] char_arr, int i)
{
if(i==char_arr.length-1)
{
// print the shuffled string
String str="";
for(int j=0; j<char_arr.length; j++)
{
str=str+char_arr[j];
}
System.out.println(str);
}
else
{
for(int j=i; j<char_arr.length; j++)
{
char tmp = char_arr[i];
char_arr[i] = char_arr[j];
char_arr[j] = tmp;
helper(char_arr,i+1);
char tmp1 = char_arr[i];
char_arr[i] = char_arr[j];
char_arr[j] = tmp1;
}
}
}
การใช้งานหลาม
def getPermutation(s, prefix=''):
if len(s) == 0:
print prefix
for i in range(len(s)):
getPermutation(s[0:i]+s[i+1:len(s)],prefix+s[i] )
getPermutation('abcd','')
สิ่งนี้ใช้ได้กับฉัน ..
import java.util.Arrays;
public class StringPermutations{
public static void main(String args[]) {
String inputString = "ABC";
permute(inputString.toCharArray(), 0, inputString.length()-1);
}
public static void permute(char[] ary, int startIndex, int endIndex) {
if(startIndex == endIndex){
System.out.println(String.valueOf(ary));
}else{
for(int i=startIndex;i<=endIndex;i++) {
swap(ary, startIndex, i );
permute(ary, startIndex+1, endIndex);
swap(ary, startIndex, i );
}
}
}
public static void swap(char[] ary, int x, int y) {
char temp = ary[x];
ary[x] = ary[y];
ary[y] = temp;
}
}
ใช้การเรียกซ้ำ
เมื่ออินพุตเป็นสตริงว่างการเปลี่ยนแปลงเพียงอย่างเดียวคือสตริงว่างลองใช้ตัวอักษรแต่ละตัวในสตริงโดยทำให้เป็นตัวอักษรตัวแรกจากนั้นค้นหาการเรียงสับเปลี่ยนทั้งหมดของตัวอักษรที่เหลือโดยใช้การเรียกซ้ำ
import java.util.ArrayList;
import java.util.List;
class Permutation {
private static List<String> permutation(String prefix, String str) {
List<String> permutations = new ArrayList<>();
int n = str.length();
if (n == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < n; i++) {
permutations.addAll(permutation(prefix + str.charAt(i), str.substring(i + 1, n) + str.substring(0, i)));
}
}
return permutations;
}
public static void main(String[] args) {
List<String> perms = permutation("", "abcd");
String[] array = new String[perms.size()];
for (int i = 0; i < perms.size(); i++) {
array[i] = perms.get(i);
}
int x = array.length;
for (final String anArray : array) {
System.out.println(anArray);
}
}
}
ให้ฉันพยายามจัดการปัญหานี้ด้วย Kotlin:
fun <T> List<T>.permutations(): List<List<T>> {
//escape case
if (this.isEmpty()) return emptyList()
if (this.size == 1) return listOf(this)
if (this.size == 2) return listOf(listOf(this.first(), this.last()), listOf(this.last(), this.first()))
//recursive case
return this.flatMap { lastItem ->
this.minus(lastItem).permutations().map { it.plus(lastItem) }
}
}
แนวคิดหลัก: แบ่งรายการยาว ๆ เป็นรายการขนาดเล็ก + เรียกซ้ำ
คำตอบแบบยาวพร้อมรายการตัวอย่าง [1, 2, 3, 4]:
แม้กระทั่งในรายการ 4 รายการมันก็ค่อนข้างสับสนทำให้การพยายามเรียงลำดับพีชคณิตที่เป็นไปได้ทั้งหมดในหัวของคุณและสิ่งที่เราต้องทำก็คือหลีกเลี่ยงสิ่งนั้น มันง่ายสำหรับเราที่จะเข้าใจวิธีการเรียงสับเปลี่ยนรายการขนาด 0, 1 และ 2 ทั้งหมดดังนั้นสิ่งที่เราต้องทำคือแยกมันออกเป็นขนาดใดก็ได้และรวมกลับอย่างถูกต้อง ลองนึกภาพเครื่องแจ็คพอต: อัลกอริทึมนี้จะเริ่มหมุนจากขวาไปซ้ายและเขียนลงไป
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class hello {
public static void main(String[] args) throws IOException {
hello h = new hello();
h.printcomp();
}
int fact=1;
public void factrec(int a,int k){
if(a>=k)
{fact=fact*k;
k++;
factrec(a,k);
}
else
{System.out.println("The string will have "+fact+" permutations");
}
}
public void printcomp(){
String str;
int k;
Scanner in = new Scanner(System.in);
System.out.println("enter the string whose permutations has to b found");
str=in.next();
k=str.length();
factrec(k,1);
String[] arr =new String[fact];
char[] array = str.toCharArray();
while(p<fact)
printcomprec(k,array,arr);
// if incase u need array containing all the permutation use this
//for(int d=0;d<fact;d++)
//System.out.println(arr[d]);
}
int y=1;
int p = 0;
int g=1;
int z = 0;
public void printcomprec(int k,char array[],String arr[]){
for (int l = 0; l < k; l++) {
for (int b=0;b<k-1;b++){
for (int i=1; i<k-g; i++) {
char temp;
String stri = "";
temp = array[i];
array[i] = array[i + g];
array[i + g] = temp;
for (int j = 0; j < k; j++)
stri += array[j];
arr[z] = stri;
System.out.println(arr[z] + " " + p++);
z++;
}
}
char temp;
temp=array[0];
array[0]=array[y];
array[y]=temp;
if (y >= k-1)
y=y-(k-1);
else
y++;
}
if (g >= k-1)
g=1;
else
g++;
}
}
/** Returns an array list containing all
* permutations of the characters in s. */
public static ArrayList<String> permute(String s) {
ArrayList<String> perms = new ArrayList<>();
int slen = s.length();
if (slen > 0) {
// Add the first character from s to the perms array list.
perms.add(Character.toString(s.charAt(0)));
// Repeat for all additional characters in s.
for (int i = 1; i < slen; ++i) {
// Get the next character from s.
char c = s.charAt(i);
// For each of the strings currently in perms do the following:
int size = perms.size();
for (int j = 0; j < size; ++j) {
// 1. remove the string
String p = perms.remove(0);
int plen = p.length();
// 2. Add plen + 1 new strings to perms. Each new string
// consists of the removed string with the character c
// inserted into it at a unique location.
for (int k = 0; k <= plen; ++k) {
perms.add(p.substring(0, k) + c + p.substring(k));
}
}
}
}
return perms;
}
นี่เป็นวิธีการเรียกซ้ำแบบมินิมอลที่เรียบง่ายใน Java
public static ArrayList<String> permutations(String s) {
ArrayList<String> out = new ArrayList<String>();
if (s.length() == 1) {
out.add(s);
return out;
}
char first = s.charAt(0);
String rest = s.substring(1);
for (String permutation : permutations(rest)) {
out.addAll(insertAtAllPositions(first, permutation));
}
return out;
}
public static ArrayList<String> insertAtAllPositions(char ch, String s) {
ArrayList<String> out = new ArrayList<String>();
for (int i = 0; i <= s.length(); ++i) {
String inserted = s.substring(0, i) + ch + s.substring(i);
out.add(inserted);
}
return out;
}
เราสามารถใช้แฟคทอเรียลเพื่อค้นหาว่ามีสตริงจำนวนเท่าใดที่เริ่มต้นด้วยตัวอักษรเฉพาะ
ตัวอย่าง: abcd
ใช้การป้อนข้อมูล สตริงจะเริ่มต้นด้วยตัวอักษรของทุก(3!) == 6
abcd
static public int facts(int x){
int sum = 1;
for (int i = 1; i < x; i++) {
sum *= (i+1);
}
return sum;
}
public static void permutation(String str) {
char[] str2 = str.toCharArray();
int n = str2.length;
int permutation = 0;
if (n == 1) {
System.out.println(str2[0]);
} else if (n == 2) {
System.out.println(str2[0] + "" + str2[1]);
System.out.println(str2[1] + "" + str2[0]);
} else {
for (int i = 0; i < n; i++) {
if (true) {
char[] str3 = str.toCharArray();
char temp = str3[i];
str3[i] = str3[0];
str3[0] = temp;
str2 = str3;
}
for (int j = 1, count = 0; count < facts(n-1); j++, count++) {
if (j != n-1) {
char temp1 = str2[j+1];
str2[j+1] = str2[j];
str2[j] = temp1;
} else {
char temp1 = str2[n-1];
str2[n-1] = str2[1];
str2[1] = temp1;
j = 1;
} // end of else block
permutation++;
System.out.print("permutation " + permutation + " is -> ");
for (int k = 0; k < n; k++) {
System.out.print(str2[k]);
} // end of loop k
System.out.println();
} // end of loop j
} // end of loop i
}
}
นี่คือสิ่งที่ฉันทำผ่านความเข้าใจพื้นฐานของการเรียกใช้ฟังก์ชันการเรียงลำดับและการเรียกซ้ำ ใช้เวลาสักครู่ แต่ทำได้อย่างอิสระ
public class LexicographicPermutations {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="abc";
List<String>combinations=new ArrayList<String>();
combinations=permutations(s);
Collections.sort(combinations);
System.out.println(combinations);
}
private static List<String> permutations(String s) {
// TODO Auto-generated method stub
List<String>combinations=new ArrayList<String>();
if(s.length()==1){
combinations.add(s);
}
else{
for(int i=0;i<s.length();i++){
List<String>temp=permutations(s.substring(0, i)+s.substring(i+1));
for (String string : temp) {
combinations.add(s.charAt(i)+string);
}
}
}
return combinations;
}}
ซึ่งจะสร้างเอาท์พุท[abc, acb, bac, bca, cab, cba]
เป็น
ตรรกะพื้นฐานที่อยู่เบื้องหลังมันคือ
สำหรับตัวละครแต่ละตัวให้พิจารณาเป็นตัวอักษรตัวที่ 1 และค้นหาการรวมกันของตัวละครที่เหลือ [abc](Combination of abc)->
เช่น
a->[bc](a x Combination of (bc))->{abc,acb}
b->[ac](b x Combination of (ac))->{bac,bca}
c->[ab](c x Combination of (ab))->{cab,cba}
และแล้วซ้ำโทรแต่ละ[bc]
, [ac]
และ[ab]
เป็นอิสระ
การใช้งาน Java โดยไม่ต้องเรียกซ้ำ
public Set<String> permutate(String s){
Queue<String> permutations = new LinkedList<String>();
Set<String> v = new HashSet<String>();
permutations.add(s);
while(permutations.size()!=0){
String str = permutations.poll();
if(!v.contains(str)){
v.add(str);
for(int i = 0;i<str.length();i++){
String c = String.valueOf(str.charAt(i));
permutations.add(str.substring(i+1) + c + str.substring(0,i));
}
}
}
return v;
}
// แทรกอักขระแต่ละตัวลงในรายการอาร์เรย์
static ArrayList al = new ArrayList();
private static void findPermutation (String str){
for (int k = 0; k < str.length(); k++) {
addOneChar(str.charAt(k));
}
}
//insert one char into ArrayList
private static void addOneChar(char ch){
String lastPerStr;
String tempStr;
ArrayList locAl = new ArrayList();
for (int i = 0; i < al.size(); i ++ ){
lastPerStr = al.get(i).toString();
//System.out.println("lastPerStr: " + lastPerStr);
for (int j = 0; j <= lastPerStr.length(); j++) {
tempStr = lastPerStr.substring(0,j) + ch +
lastPerStr.substring(j, lastPerStr.length());
locAl.add(tempStr);
//System.out.println("tempStr: " + tempStr);
}
}
if(al.isEmpty()){
al.add(ch);
} else {
al.clear();
al = locAl;
}
}
private static void printArrayList(ArrayList al){
for (int i = 0; i < al.size(); i++) {
System.out.print(al.get(i) + " ");
}
}
//Rotate and create words beginning with all letter possible and push to stack 1
//Read from stack1 and for each word create words with other letters at the next location by rotation and so on
/* eg : man
1. push1 - man, anm, nma
2. pop1 - nma , push2 - nam,nma
pop1 - anm , push2 - amn,anm
pop1 - man , push2 - mna,man
*/
public class StringPermute {
static String str;
static String word;
static int top1 = -1;
static int top2 = -1;
static String[] stringArray1;
static String[] stringArray2;
static int strlength = 0;
public static void main(String[] args) throws IOException {
System.out.println("Enter String : ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader bfr = new BufferedReader(isr);
str = bfr.readLine();
word = str;
strlength = str.length();
int n = 1;
for (int i = 1; i <= strlength; i++) {
n = n * i;
}
stringArray1 = new String[n];
stringArray2 = new String[n];
push(word, 1);
doPermute();
display();
}
public static void push(String word, int x) {
if (x == 1)
stringArray1[++top1] = word;
else
stringArray2[++top2] = word;
}
public static String pop(int x) {
if (x == 1)
return stringArray1[top1--];
else
return stringArray2[top2--];
}
public static void doPermute() {
for (int j = strlength; j >= 2; j--)
popper(j);
}
public static void popper(int length) {
// pop from stack1 , rotate each word n times and push to stack 2
if (top1 > -1) {
while (top1 > -1) {
word = pop(1);
for (int j = 0; j < length; j++) {
rotate(length);
push(word, 2);
}
}
}
// pop from stack2 , rotate each word n times w.r.t position and push to
// stack 1
else {
while (top2 > -1) {
word = pop(2);
for (int j = 0; j < length; j++) {
rotate(length);
push(word, 1);
}
}
}
}
public static void rotate(int position) {
char[] charstring = new char[100];
for (int j = 0; j < word.length(); j++)
charstring[j] = word.charAt(j);
int startpos = strlength - position;
char temp = charstring[startpos];
for (int i = startpos; i < strlength - 1; i++) {
charstring[i] = charstring[i + 1];
}
charstring[strlength - 1] = temp;
word = new String(charstring).trim();
}
public static void display() {
int top;
if (top1 > -1) {
while (top1 > -1)
System.out.println(stringArray1[top1--]);
} else {
while (top2 > -1)
System.out.println(stringArray2[top2--]);
}
}
}
อีกวิธีง่ายๆคือการวนลูปผ่านสตริงเลือกอักขระที่ยังไม่ได้ใช้และวางลงในบัฟเฟอร์ดำเนินการวนรอบต่อไปจนกระทั่งขนาดบัฟเฟอร์เท่ากับความยาวสตริง ฉันชอบโซลูชันติดตามย้อนหลังที่ดีกว่าเพราะ:
นี่คือรหัส java:
List<String> permute(String str) {
if (str == null) {
return null;
}
char[] chars = str.toCharArray();
boolean[] used = new boolean[chars.length];
List<String> res = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
Arrays.sort(chars);
helper(chars, used, sb, res);
return res;
}
void helper(char[] chars, boolean[] used, StringBuilder sb, List<String> res) {
if (sb.length() == chars.length) {
res.add(sb.toString());
return;
}
for (int i = 0; i < chars.length; i++) {
// avoid duplicates
if (i > 0 && chars[i] == chars[i - 1] && !used[i - 1]) {
continue;
}
// pick the character that has not used yet
if (!used[i]) {
used[i] = true;
sb.append(chars[i]);
helper(chars, used, sb, res);
// back tracking
sb.deleteCharAt(sb.length() - 1);
used[i] = false;
}
}
}
อินพุต str: 1231
รายการเอาท์พุท: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}
พบว่ามีการเรียงลำดับผลลัพธ์และไม่มีผลลัพธ์ที่ซ้ำกัน
การเรียกซ้ำไม่จำเป็นแม้ว่าคุณจะสามารถคำนวณการเปลี่ยนแปลงใด ๆ โดยตรงโซลูชันนี้ใช้ข้อมูลทั่วไปในการเรียงลำดับอาร์เรย์ใด ๆ
นี่คือข้อมูลที่ดีเกี่ยวกับ algorihtm นี้
สำหรับนักพัฒนาC # นี่คือการใช้งานที่มีประโยชน์มากขึ้น
public static void main(String[] args) {
String word = "12345";
Character[] array = ArrayUtils.toObject(word.toCharArray());
long[] factorials = Permutation.getFactorials(array.length + 1);
for (long i = 0; i < factorials[array.length]; i++) {
Character[] permutation = Permutation.<Character>getPermutation(i, array, factorials);
printPermutation(permutation);
}
}
private static void printPermutation(Character[] permutation) {
for (int i = 0; i < permutation.length; i++) {
System.out.print(permutation[i]);
}
System.out.println();
}
ขั้นตอนวิธีการนี้มีO (n) เวลาและพื้นที่ซับซ้อนในการคำนวณแต่ละเปลี่ยนแปลง
public class Permutation {
public static <T> T[] getPermutation(long permutationNumber, T[] array, long[] factorials) {
int[] sequence = generateSequence(permutationNumber, array.length - 1, factorials);
T[] permutation = generatePermutation(array, sequence);
return permutation;
}
public static <T> T[] generatePermutation(T[] array, int[] sequence) {
T[] clone = array.clone();
for (int i = 0; i < clone.length - 1; i++) {
swap(clone, i, i + sequence[i]);
}
return clone;
}
private static int[] generateSequence(long permutationNumber, int size, long[] factorials) {
int[] sequence = new int[size];
for (int j = 0; j < sequence.length; j++) {
long factorial = factorials[sequence.length - j];
sequence[j] = (int) (permutationNumber / factorial);
permutationNumber = (int) (permutationNumber % factorial);
}
return sequence;
}
private static <T> void swap(T[] array, int i, int j) {
T t = array[i];
array[i] = array[j];
array[j] = t;
}
public static long[] getFactorials(int length) {
long[] factorials = new long[length];
long factor = 1;
for (int i = 0; i < length; i++) {
factor *= i <= 1 ? 1 : i;
factorials[i] = factor;
}
return factorials;
}
}
การเรียงสับเปลี่ยนของสตริง:
public static void main(String args[]) {
permu(0,"ABCD");
}
static void permu(int fixed,String s) {
char[] chr=s.toCharArray();
if(fixed==s.length())
System.out.println(s);
for(int i=fixed;i<s.length();i++) {
char c=chr[i];
chr[i]=chr[fixed];
chr[fixed]=c;
permu(fixed+1,new String(chr));
}
}
นี่เป็นอีกวิธีที่ง่ายกว่าในการทำการเรียงสับเปลี่ยนของสตริง
public class Solution4 {
public static void main(String[] args) {
String a = "Protijayi";
per(a, 0);
}
static void per(String a , int start ) {
//bse case;
if(a.length() == start) {System.out.println(a);}
char[] ca = a.toCharArray();
//swap
for (int i = start; i < ca.length; i++) {
char t = ca[i];
ca[i] = ca[start];
ca[start] = t;
per(new String(ca),start+1);
}
}//per
}
การนำ Java ไปใช้เพื่อพิมพ์พีชคณิตทั้งหมดของสตริงที่กำหนดโดยพิจารณาอักขระที่ซ้ำกันและพิมพ์เฉพาะอักขระที่ไม่ซ้ำกันดังต่อไปนี้:
import java.util.Set;
import java.util.HashSet;
public class PrintAllPermutations2
{
public static void main(String[] args)
{
String str = "AAC";
PrintAllPermutations2 permutation = new PrintAllPermutations2();
Set<String> uniqueStrings = new HashSet<>();
permutation.permute("", str, uniqueStrings);
}
void permute(String prefixString, String s, Set<String> set)
{
int n = s.length();
if(n == 0)
{
if(!set.contains(prefixString))
{
System.out.println(prefixString);
set.add(prefixString);
}
}
else
{
for(int i=0; i<n; i++)
{
permute(prefixString + s.charAt(i), s.substring(0,i) + s.substring(i+1,n), set);
}
}
}
}
/*
* eg: abc =>{a,bc},{b,ac},{c,ab}
* =>{ca,b},{cb,a}
* =>cba,cab
* =>{ba,c},{bc,a}
* =>bca,bac
* =>{ab,c},{ac,b}
* =>acb,abc
*/
public void nonRecpermute(String prefix, String word)
{
String[] currentstr ={prefix,word};
Stack<String[]> stack = new Stack<String[]>();
stack.add(currentstr);
while(!stack.isEmpty())
{
currentstr = stack.pop();
String currentPrefix = currentstr[0];
String currentWord = currentstr[1];
if(currentWord.equals(""))
{
System.out.println("Word ="+currentPrefix);
}
for(int i=0;i<currentWord.length();i++)
{
String[] newstr = new String[2];
newstr[0]=currentPrefix + String.valueOf(currentWord.charAt(i));
newstr[1] = currentWord.substring(0, i);
if(i<currentWord.length()-1)
{
newstr[1] = newstr[1]+currentWord.substring(i+1);
}
stack.push(newstr);
}
}
}
สิ่งนี้สามารถทำได้ซ้ำ ๆ โดยใส่ตัวอักษรแต่ละตัวของสตริงในสถานที่ทั้งหมดของผลลัพธ์บางส่วนก่อนหน้านี้
เราเริ่มต้นด้วย[A]
ซึ่งมีB
กลายเป็น[BA, AB]
และมีC
,[CBA, BCA, BAC, CAB, etc]
.
เวลาทำงานจะเป็นO(n!)
ที่สำหรับกรณีทดสอบเป็นABCD
1 x 2 x 3 x 4
ในผลิตภัณฑ์ด้านบน1
มีไว้สำหรับA
ใช้ทำ2
เพื่อB
ฯลฯ
ตัวอย่างโผ:
void main() {
String insertAt(String a, String b, int index)
{
return a.substring(0, index) + b + a.substring(index);
}
List<String> Permute(String word) {
var letters = word.split('');
var p_list = [ letters.first ];
for (var c in letters.sublist(1)) {
var new_list = [ ];
for (var p in p_list)
for (int i = 0; i <= p.length; i++)
new_list.add(insertAt(p, c, i));
p_list = new_list;
}
return p_list;
}
print(Permute("ABCD"));
}
นี่คือการใช้งานจาวา:
/* All Permutations of a String */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Complexity O(n*n!) */
class Ideone
{
public static ArrayList<String> strPerm(String str, ArrayList<String> list)
{
int len = str.length();
if(len==1){
list.add(str);
return list;
}
list = strPerm(str.substring(0,len-1),list);
int ls = list.size();
char ap = str.charAt(len-1);
for(int i=0;i<ls;i++){
String temp = list.get(i);
int tl = temp.length();
for(int j=0;j<=tl;j++){
list.add(temp.substring(0,j)+ap+temp.substring(j,tl));
}
}
while(true){
String temp = list.get(0);
if(temp.length()<len)
list.remove(temp);
else
break;
}
return list;
}
public static void main (String[] args) throws java.lang.Exception
{
String str = "abc";
ArrayList<String> list = new ArrayList<>();
list = strPerm(str,list);
System.out.println("Total Permutations : "+list.size());
for(int i=0;i<list.size();i++)
System.out.println(list.get(i));
}
}