对一道算法题的思考
下面要说的这道题是多天前一位网友提问的,当时没仔细考虑。虽然早已经结帖了。但是最终好像大家都没有给出很可行的解决方法。
原问题是“写出用 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
这些字符拼出来的所有长度小于等于12位的文件名(扩展名不用考虑)。”
今天看算法书时,看到递归算法里面有一个应用,是讲“变位字”的。虽然不能直接拿来解决这个问题,但是经本人稍加改动,竟然可以完美解决上面的那个问题。
首先说一下变位字是怎么回事。假设想要列出一个指定单词的所有变位字,也就是列出该词的全排列,它们都是由原来这个单词的字母组成的。我们称这个工作是变位一个单词或称全排列一个单词的字母。用递归的方法来编程实现全排列单词的思路是:
假设这个词有n个字母:1,全排列最右边的n-1个字母。2,轮换所有n个字母。3,重复以上步骤n 次。很显然的递归思想。
轮换的意思是所有字母向左移一位,但是最左边的字母例外,它“轮换”至最右边字母的后边。下面是实现递归得到所有字母排列的
方法:
上面那个方法还调用了显示方法(显示目前的整个单词),和轮换方法rotate(),可以看出它是在递归的最里层实现打印整个单词的字母序列。既然递归的最里层可以打印整个单词,那么当从最里层返回时,是不是可以显示长度为n-1的单词,也就是说这个长度的单词字母是原单词的一部分,依次类推,每层的递归返回都可以显示更短长度的单词。因此要在上面方法的for循环体中,加入
显示方法,以显示由原单词的字母的一部分组合成的单词。而更进一步,如果想要做到长度小于等于某个数的字母组合,只需要在显示方法中进行显示之前判断一下当前层的深度。于是,这个问题就算完整地解决了。
以上代码在算法书作者的原代码基础上修改得到,为了测试方便,没有固定原单词,而是在控制台手工输入,也就是说只要输入由字母组成的字符串(当然也可以是“1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”),就可以按要求打印出所有的字符组合,并且统计字符个数。当然为了便于验证,可以输入短一点的单词试验一下,看是否正确。
以上是本人的一点愚见,有何不妥之处还请大家指出,或者有更好的方法来解决那个问题,不妨可以一起讨论,共同提高。
原问题是“写出用 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
这些字符拼出来的所有长度小于等于12位的文件名(扩展名不用考虑)。”
今天看算法书时,看到递归算法里面有一个应用,是讲“变位字”的。虽然不能直接拿来解决这个问题,但是经本人稍加改动,竟然可以完美解决上面的那个问题。
首先说一下变位字是怎么回事。假设想要列出一个指定单词的所有变位字,也就是列出该词的全排列,它们都是由原来这个单词的字母组成的。我们称这个工作是变位一个单词或称全排列一个单词的字母。用递归的方法来编程实现全排列单词的思路是:
假设这个词有n个字母:1,全排列最右边的n-1个字母。2,轮换所有n个字母。3,重复以上步骤n 次。很显然的递归思想。
轮换的意思是所有字母向左移一位,但是最左边的字母例外,它“轮换”至最右边字母的后边。下面是实现递归得到所有字母排列的
方法:
public static void doAnagram(int newSize)
{
if(newSize == 1) //if innermost,go no further
{
displayWord();//打印出目前字母数组的单词
return;
}
for (int j=0; j<newSize; j++) //for each position
{
doAnagram(newSize - 1); //anagram remaining
rotate(newSize); //rotate word
}
}
上面那个方法还调用了显示方法(显示目前的整个单词),和轮换方法rotate(),可以看出它是在递归的最里层实现打印整个单词的字母序列。既然递归的最里层可以打印整个单词,那么当从最里层返回时,是不是可以显示长度为n-1的单词,也就是说这个长度的单词字母是原单词的一部分,依次类推,每层的递归返回都可以显示更短长度的单词。因此要在上面方法的for循环体中,加入
显示方法,以显示由原单词的字母的一部分组合成的单词。而更进一步,如果想要做到长度小于等于某个数的字母组合,只需要在显示方法中进行显示之前判断一下当前层的深度。于是,这个问题就算完整地解决了。
import java.io.*;
class AnagramApp1
{
static int size;
static int count;
static char[] arrChar = new char[100];
public static void main(String[] args) throws IOException
{
System.out.print("Enter a word:");
String input = getString();
size = input.length();
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) //if innermost,go no further
{
displayWord(newSize); //最后一层,输出的是全部字符的可能组合
return;
}
for (int j=0; j<newSize; j++) //for each position
{
doAnagram(newSize - 1); //anagram remaining
displayWord(newSize); //我加的显示语句,用于显示所有长度小于原单词长度的单词
rotate(newSize); //rotate word
}
}
public static void rotate(int newSize)
{
int j;
int position = size - newSize;
char temp = arrChar[position]; //save first letter
for (j=position+1; j<size; j++) //shift others left
{
arrChar[j-1] = arrChar[j];
}
arrChar[j-1] = temp; //put first on right
}
public static void displayWord(int newSize) //经过改造的显示方法,要接收一个参数以判断当前的递归层数
{
if(count < 99)
System.out.print(" ");
if(count < 9)
System.out.print(" ");
if(size-newSize+1 <= 2) //加入的判断,2就表示长度小于等于2的单词打印出来
{
System.out.print(++count + " ");
for(int j=0;j < size-newSize+1; j++)
{
System.out.print(arrChar[j]);
}
}
System.out.print(" ");
System.out.flush();
if(count%6 == 0)
System.out.println("");
}
public static String getString() throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
} //end class AnagramApp
以上代码在算法书作者的原代码基础上修改得到,为了测试方便,没有固定原单词,而是在控制台手工输入,也就是说只要输入由字母组成的字符串(当然也可以是“1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”),就可以按要求打印出所有的字符组合,并且统计字符个数。当然为了便于验证,可以输入短一点的单词试验一下,看是否正确。
以上是本人的一点愚见,有何不妥之处还请大家指出,或者有更好的方法来解决那个问题,不妨可以一起讨论,共同提高。
...全文
相关推荐
leetcode知乎-ARTS:算法复习技巧分享
leetcode 知乎 ARTS 单词 含义 Algorithm Leetcode 上 AC 一道算法题 Review 阅读并点评一篇英文技术文章, 翻译下就更好了 Tip 学习一个技术技巧 Share 分享一篇有观点和思考的技术文章 2019 一 二 三 四 Others
leetcode卡-ARTS:艺术
leetcode卡 ARTS Algorithm 每周一道leetcode算法题 Review 阅读并点评一篇英文技术文章 Tip 学习一个技术技巧 Share 分享一篇有观点和思考的技术文章 :memo:尝试着进行ARTS打卡计划...
上班时间刷leetcode-leetcode:每日算法题
上班时间刷leetcode leetcode每日道算法题 搬出家做开发有段时间,发现自己在算法方便比较薄弱,为了弥补自的先天不足,定了小计划,每天上班之余刷刷算法题。
互联网大厂内推及大厂面经整理,并且每天一道面试题推送 每天五分钟,半年大厂中
【源码预览】:https://renmaiwang.cn/s/xde5i (最新版、最全版本)互联网大厂内推及大厂面经整理,并且每天一道面试题推送。每天五分钟,半年大厂中
2008年百度之星算法题
2008年百度之星算法题,对算法感兴趣的可以看看哦,这是第二天的题


Java SE
