-
生成一个长度是3的随机字符串,把这个字符串作为当做密码
-
使用穷举法生成长度是3个字符串,匹配上述生成的密码
要求: 分别使用多层for循环 和 递归解决上述问题
1.穷举法:
穷举算法,依赖计算机强大的计算能力,来穷举每一种可能的情况,以达到解决问题的目的,也叫枚举法、暴力破解法。
基本思想———逐一列举问题所涉及的所有情形,并根据问题提出的条件进行检验从而找到可能的解 。
方法步骤———确定枚举对象、枚举范围、判断条件;循环验证每一个解
2.递归:
递归的思想:
以此类推是递归的基本思想。
具体来讲就是把规模大的问题转化为规模小的相似的子问题来解决。在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况。另外这个解决问题的函数必须有明显的结束条件,这样就不会产生无限递归的情况了。
递归的两个条件:
可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式。(自身调用)
存在一种简单情境,可以使递归在简单情境下退出。(递归出口)
递归三要素:
一定有一种可以退出程序的情况;
总是在尝试将一个问题化简到更小的规模
父问题与子问题不能有重叠的部分
递归:自已(方法)调用自已
例子:用递归把目录下所有的目录及文件全部显示出来
方法一:多层循环方式
package day6;
/*
* 练习-穷举法破解密码
* 1. 生成一个长度是3的随机字符串,把这个字符串作为当做密码
2. 使用穷举法生成长度是3个字符串,匹配上述生成的密码
要求: 分别使用多层for循环 和 递归解决上述问题
*/
public class TestNumber10 {
public static void main(String[] args) {
//多层循环方式
String password=randomString(3);//首先通过调用randomString()方法随机生成一个字符串作为密码,并将它赋值给password
System.out.println("密码是:"+password);//输出这个密码
char[]guesspassword=new char[3];//新建一个长度为3的空数组
outloop://设置一个标签,在break的时候使用该标签,即能达到结束多重嵌套循环的效果
//开始多层循环,也就是穷举
for(short i ='0';i<='z';i++){
for(short j ='0';j<='z';j++){
for(short k ='0';k<='z';k++){
if(!isLetterOrDigit(i,j,k)){//调用isLetterOrDigt()方法,如果i,j,k有一个不符合条件,就跳出当前循环,并开始下一次循环
continue;
}
//如果i,j,k都符合条件,那就分别把i,j,k赋值给guesspassword数组的三个位置
guesspassword[0]=(char)i;
guesspassword[1]=(char)j;
guesspassword[2]=(char)k;
//这样就得到了穷举出来的密码
String guess = new String(guesspassword);
//System.out.println("穷举出来的密码是:"+guess);
if(guess.equals(password))//将穷举出来的密码与原密码进行比较,如果二者一致,执行if
{
System.out.println("找到了,密码是:"+guess);
break outloop;
}
}
}
}
}
private static boolean isLetterOrDigit(short i,short j ,short k){//判断i,j,k是不是符合条件
return (Character.isLetterOrDigit(i))&&(Character.isLetterOrDigit(j))&&Character.isLetter(k);
}
private static String randomString(int length){//随机生成一个长度为3的字符串,注意这里有参数Length,是字符串的长度
String pool="";
for(int i ='0';i<='9';i++){
pool+=(char)i;
}
for(int i ='a';i<='z';i++){
pool+=(char)i;
}
for(int i ='A';i<='Z';i++){
pool+=(char)i;
}
char cs[]=new char[length];//参数传到了这里,也就是new char[3]
for(int i =0;i<cs.length;i++){//这样就可以按照cs的长度(也就是password的长度)来随机分配数字或者字母了
int index= (int)(Math.random()*(pool.length()));
cs[i]=pool.charAt(index);//把字符串随机下标的一个字符放入每一个数组元素
}
String result = String.valueOf(cs); //把字符数组转换成字符串,记住
return result;
}
}
方法二:递归方式
package day6;
/*
* 练习-穷举法破解密码
* 1. 生成一个长度是3的随机字符串,把这个字符串作为当做密码
2. 使用穷举法生成长度是3个字符串,匹配上述生成的密码
要求: 分别使用多层for循环 和 递归解决上述问题
*/
public class TestNumber11 {
public static boolean found = false;
public static void main(String[] args) {
String password= randomString(3);//定义了一个Password字符串,并调用randomString方法随机生成了一个长度为3的字符串,赋值给了password
System.out.println("密码是:"+password);
char[]guessPassword= new char[password.length()];//定义了一个数组guessPassword,她的长度和password的长度一样
generatePassword(guessPassword,password);//调用generatePassword方法,注意里面有两个参数
}
private static void generatePassword(char[]guessPassword,String password){//定义了generatePassword方法,有两个参数
generatePassword(guessPassword,0,password);//方法内又调用了generatePassword方法,注意这里是三个参数
}
private static void generatePassword(char[] guessPassword,int index,String password){//将generatePassword方法重载,改成了三个参数,方法体也有了改变
if(found)
//这里found如果是false,就不执行if语句,然后继续执行for循环,也就表示false的时候没有找到密码,继续循环;
//如果found是true,就代表找到了密码,那么就执行if语句,返回一个空,这里已经有了返回值给generatePassword()方法,那么就不在继续向下执行for循环了,这里要注意。
return;
for(short i ='0';i<='z';i++){
char c =(char)i;//定义一个字符变量c,将i的值赋值给c,并强制类型转换
if(!Character.isLetterOrDigit(c))//如果c不符合是字母或者数字的要求,跳出本次循环
continue;
guessPassword[index]=c;//如果c符合要求,就把c赋值给参入的index参数对应的数组的位置
if(index!=guessPassword.length-1){//如果index的值还没有到数组的最后一个位置的值,就继续调用generatePassword
//这里index继续向后移动,所以变成里index+1,以此类推
generatePassword(guessPassword,index+1,password);
}
else
{//如果index已经到了数组的最后一个位置,就执行else后面这里的方法体
String guess = new String(guessPassword);//把guessPassword赋值给定义的字符串guess
//System.out.println("穷举出来的密码是:" + guess);
if(guess.equals(password)){//比较guess和原密码
System.out.println("找到了,密码是" + guess);
found =true;//找到了密码。将found改成true,返回空
return;
}
}
}
}
private static String randomString(int length) {//randomString函数的内容:生成长度为3的随机字符串
String pool = "";
for (short i = '0'; i <= '9'; i++) {
pool += (char) i;
}
for (short i = 'a'; i <= 'z'; i++) {
pool += (char) i;
}
for (short i = 'A'; i <= 'Z'; i++) {
pool += (char) i;
}
char cs[] = new char[length];
for (int i = 0; i < cs.length; i++) {
int index = (int) (Math.random() * pool.length());
cs[i] = pool.charAt(index);
}
String result = new String(cs);
return result;
}
}
本文详细介绍了如何使用穷举法和递归策略来破解长度为3的字符串密码。首先,通过生成随机3字符密码,然后分别使用多层for循环和递归方法穷举所有可能的字符串组合进行匹配。穷举法基于逐一列举所有情况并检查条件,而递归则通过函数自我调用来解决规模较小的类似问题,具备明确的终止条件和问题规模缩小的特点。文中还给出了递归在文件系统遍历中的应用实例。

4169

被折叠的 条评论
为什么被折叠?



