先给大家讲一个故事:
这是一个风云变幻的时代,几个字母争先恐后的抢着做老大,但是姜还是老的辣,经过一番折腾,最后的最后,几个字母还是回到最初的样子,坐回他们原来的位置,一起干回他们原来的事情——(构成一个完整的"单词"),老大还是那个老大...
(啊...真是一个有趣的故事...手动滑稽)
为了让大家更好的理解,我将4个字母构成的单词(不一定是真正的单词,只要由四个字母构成,我们在这里就把它叫做单词)前面部分进行详细讲解,后面的以此类推:
例子:abcd
这是一个逆向过程:
知道d(一个字母无法进行交换,不打印)→ 推到cd(执行打印操作,随后进行前移操作),
[暂且看起来执行的像是交换操作,其实到后面就可以看出来是前移操作了]
前移过程:将c后面的字母d往前移,把字母c放在最后面,构成dc
执行完前移rotate方法后,仍在循环体内,所以仍在dc中(前面已经完成了前移操作),执行打印操作,然后再进行前移操作,
前移过程:将d后面的字母c往前移,把字母d放在最后面,构成cd
此时你会发现又变回了abcd,两次前移操作相当于没有进行前移操作。
跳出循环:推到bcd→因为长度不为2故不执行打印工作(长度不为2时,相当于还保留着上一轮的"单词",前面说过进行两次前移操作相当于没有操作,如果我们这时候打印,就回造成重复)→ 进行前移操作
前移过程:将b后面的字母c跟d往前移,把字母b放在最后面,构成cdb
此时仍在循环体内:重复上一轮操作,具体如下:
cdb → db → b [return]
知道b(一个字母无法进行交换,不打印)→ 推到db(执行打印操作,进行前移操作),
[暂且看起来执行的像是交换操作,其实到后面就可以看出来是前移操作了]
前移过程:将d后面的字母b往前移,把字母d放在最后面,构成bd
执行完前移rotate方法后,仍在循环体内,所以仍在bd中(前面已经完成了前移操作),执行打印操作,然后再进行前移操作,
前移过程:将b后面的字母d往前移,把字母b放在最后面,构成db
此时你会发现又变回了acdb,两次前移操作相当于没有进行前移操作。
跳出循环:推到cdb→因为长度不为2故不执行打印工作(长度不为2时,相当于还保留着上一轮的"单词",前面说过进行两次前移操作相当于没有操作,如果我们这时候打印,就回造成重复)→ 进行前移操作
前移过程:将c后面的字母d跟b往前移,然后把字母c放在最后面,构成dbc
随后又进行一次上述的循环,最后回到bcd原来的模样,为什么呢?
(其实就是我们的前移操作,不断将第一个字母的后面往前移动,然后将第一个字母放到最后一个位置上面)
初始模样:bcd
上述在3个字母的时候进行了3次操作,把b移动到d的位置,让c做了头头即cdb
然后:
b又移动到了初始模样c的位置,让d做了头头,即dbc
然后:
b又移动到了初始模样b的位置,再次做上了头头,即bcd
经历完上述操作,相信可以看懂以下流程:
doAnagram(1) → doAnagram(2) → doAnagram(3) → doAnagram(4)
到了doAnagram(4)这里,我们又执行类似上述的工作,将a后面的字母往前移,把字母a放到最后的位置,每个字母抢着做老大,显然背后是你敲代码动了手脚让他们这样干的,这样一轮轮的前移,仍然会回到原来的模样abcd(真是有够折腾的)
下面是附注释代码:
import java.io.*;
public class Anagram {
static int size;//"单词"长度
static int count;//变换个数
static char[] arrChar = new char[100];//存放"单词"字母的数组
public static void main(String args[]) throws IOException{
System.out.println("Enter a word: ");//提示
String input = getString(); //输入一个"单词"
size =input.length();//获取"单词"长度
count = 0; //初始化变换个数count为0
for(int j=0;j<size;j++)
arrChar[j] = input.charAt(j);//将"单词"字母存放于数组中
doAnagram(size); //进行变换
}
public static void doAnagram(int newSize) {
if(newSize==1) //递归的出口:当一直缩减的"单词"长度为1时,返回。(无需做变换)
return;
for(int j=0;j<newSize;j++) {//进行递归操作
doAnagram(newSize-1);
if(newSize==2) //当只有两个字母的时候打印,只有两个字母需执行前移操作,需要打印
displayWord();
rotate(newSize);//进行前移工作
}
}
public static void rotate(int newSize) {
int j;
int position = size - newSize;//得到此时"单词"的第一个位置
char temp = arrChar[position];
for(j=position+1;j<size;j++)//前移
arrChar[j-1] = arrChar[j];
arrChar[j-1] = temp;//将原先的第一个字母放到最后的位置
}
//打印单词
public static void displayWord() {
if(count<99) //有这些空壳只是为了让打印出来的表格看起来漂亮一点
System.out.print(" ");//如果你不在意的话完全可以不用这样做
if(count<9)
System.out.print(" ");
System.out.print(++count+":");
for(int j=0;j<size;j++)
System.out.print(arrChar[j]);
if(count%6==0)
System.out.println();
}
//输入单词,输入的方法,Java基础--I/O流部分
public static String getString() throws IOException{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
}