题意:打印n层汉诺塔从最左边移动到最右边的全部过程
解题思路:
核心代码:
public static void hanio(int n){
leftToRight(n);
}
private static void leftToRight(int n) {
if(n==1){
System.out.println("Move 1 from left to right");
return ;
}
leftToMid(n-1);
System.out.println("Move "+n+" from left to right");
midToRight(n-1);
}
private static void midToRight(int n) {
if(n==1){
System.out.println("Move 1 from mid to right");
return ;
}
midToLeft(n-1);
System.out.println("Move "+(n)+" from mid to right");
leftToRight(n-1);
}
private static void leftToMid(int n) {
if(n==1){
System.out.println("Move 1 from left to mid");
return ;
}
leftToRight(n-1);
System.out.println("Move "+(n)+" from left to mid");
rightToMid(n-1);
}
private static void rightToMid(int n) {
if(n==1){
System.out.println("Move 1 from right to mid");
return ;
}
rightToLeft(n-1);
System.out.println("Move "+(n)+" from right to mid");
leftToMid(n-1);
}
private static void rightToLeft(int n) {
if(n==1){
System.out.println("Move 1 from right to left");
return ;
}
rightToMid(n-1);
System.out.println("Move "+(n)+" from right to left");
midToLeft(n-1);
}
private static void midToLeft(int n) {
if(n==1){
System.out.println("Move 1 from mid to left");
return ;
}
midToRight(n-1);
System.out.println("Move "+(n)+" from mid to left");
rightToLeft(n-1);
}
测试代码:
public static void main(String[] args) {
hanio(3);
}
测试结果:
题意:求斐波那契数列第n项数
**解题思路:**略(之前写过)
核心代码:
private static int fib(int n) {
if(n==1||n==2){
return 1;
}
return fib(n-1)+fib(n-2);
}
测试代码及测试结果:
题意:1.打印一个字符串的全部排列 2.打印一个字符串的全部排列,要求不要出现重复的排列
解题思路:
核心代码:
/**
* 设置更为合适的参数
*这里老师讲的版本没有再传中间参数,而是自己玩自己,相邻的交换,之后再恢复现场
* @param test
* @return
*/
private static List<String> permutation(String test) {
char[] str=test.toCharArray();
String path="";
List<String > list=new ArrayList<>();
process1(str,0,list);
return list;
}
private static void process1(char[] str, int index, List<String> list) {
if(index==str.length){
list.add(String.valueOf(str));
return ;
}
for (int i = index; i < str.length; i++) {
swap(str,index,i);
process1(str,index+1,list);
swap(str,index,i);
}
}
private static void swap(char[] str, int a, int b) {
char tmp=str[a];
str[a]=str[b];
str[b]=tmp;
}
/**
* 剪枝的方式去重,提前终止,效率更高
* @param test
* @return
*/
private static List<String> noRepeatpermutation1(String test) {
char[] str=test.toCharArray();
String path="";
List<String > list=new ArrayList<>();
process2(str,0,list);
return list;
}
private static void process2(char[] str, int index, List<String> list) {
if(index==str.length){
list.add(String.valueOf(str));
return ;
}
boolean[] visit=new boolean[256];
for (int i = index; i < str.length; i++) {
if(!visit[str[i]]){
swap(str,index,i);
process2(str,index+1,list);
swap(str,index,i);
visit[str[i]]=true;
}
}
}
/**
* 过滤方式去重
* @param test
* @return
*/
private static HashSet<String> noRepeatpermutation2(String test) {
char[] str=test.toCharArray();
String path="";
HashSet<String> set=new HashSet<>();
process3(str,0,set);
return set;
}
private static void process3(char[] str, int index, HashSet<String> set) {
if(index==str.length){
set.add(String.valueOf(str));
return ;
}
for (int i = index; i < str.length; i++) {
swap(str,index,i);
process3(str,index+1,set);
swap(str,index,i);
}
}
测试代码:
public static void main(String[] args) {
String test="acc";
List<String> ans1=permutation(test);
List<String> ans2=noRepeatpermutation1(test);
HashSet<String> ans3=noRepeatpermutation2(test);
System.out.println("未去重");
for (String str:ans1) {
System.out.println(str);
}
System.out.println("================");
System.out.println("剪枝版去重");
for (String str:ans2) {
System.out.println(str);
}
System.out.println("过滤版去重");
for(String str:ans3){
System.out.println(str);
}
}
测试结果:
题意:1.打印一个字符串的全部子序列 2.打印一个字符串的全部子序列,要求不要出现重复字面值的子序列
解题思路:
核心代码:
private static List<String> subs(String test) {
char[] str=test.toCharArray();//空的话也产生,不过是一个空串
String path="";
List<String> ans=new ArrayList<>();
process1(str,0,ans,path);
return ans;
}
private static void process1(char[] str, int index, List<String> list, String path) {
if(index==str.length){
list.add(path);
return ;
}
process1(str,index+1,list,path+str[index]);
process1(str,index+1,list,path);
}
/**
* 去重版本
* @param test
* @return
*/
private static HashSet<String> subsNoRepeat(String test) {
char[] str=test.toCharArray();//空的话也产生,不过是一个空串
String path="";
HashSet<String> set=new HashSet<>();
process2(str,0,set,path);
return set;
}
private static void process2(char[] str, int index, HashSet<String> set, String path) {
if(index==str.length){
set.add(path);
return ;
}
process2(str,index+1,set,path+str[index]);
process2(str,index+1,set,path);
}
测试代码:
public static void main(String[] args) {
String test="acc";
List<String> ans1=subs(test);
HashSet<String> ans2= subsNoRepeat(test);
for(String str:ans1){
System.out.println(str);
}
System.out.println("===============");
for(String str:ans2){
System.out.println(str);
}
}
测试结果:
题意:给定一个栈,请逆序这个栈,不能申请额外的数据结构,只能使用递归函数
解题思路:
核心代码:
private static void reverse(Stack<Integer> stack) {
if(stack.isEmpty()){
return ;
}
int tmp=f(stack);
reverse(stack);
stack.push(tmp);
}
//f函数的功能是栈底元素移除掉
//上边的元素盖下来,返回移除的栈顶元素
private static int f(Stack<Integer> stack) {
int ans=stack.pop();
if(stack.isEmpty()){
return ans;
}else{
int last=f(stack);
stack.push(ans);
return last;
}
}
测试代码:
public static void main(String[] args) {
Stack<Integer> stack=new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
reverse(stack);
while(!stack.isEmpty()){
System.out.println(stack.pop());
}
}
测试结果:
例题总结:
汉诺塔:六个子过程,打印内容为“Move ”+n +“from xx to xxx”
斐波那契:无话可说,1||2||n-1||n-2
打印全部子序列:非去重:str,index,list,path,到头了加入,要与不要;去重:使用HashSet过滤,只是换了一种收集容器
打印全排列:
总体思路,自己玩自己的(当前位置和可能成为当前位置的元素进行交换n!种可能)先交换,去下个位置,再回复现场(for循环)
非去重:str,index,list
去重:剪枝:拜访数组,256,判断当前字符在这个位置出现过没,出现过就要,没出现过就不要;过滤:换了个收集容器HashSet
使用递归逆序栈(不申请额外数据结构):f的功能拿栈底元素:if,ans,else last,push(ans),