一、二叉树
1、二叉树的递归套路:
- 假设以X节点为头,假设可以像X左树和X右树要任何信息。
- 在上一步的假设下,讨论以X为节点的树,得到答案的可能性。
- 列出所有的可能性后,确定到底需要向左树和右树要什么样的信息。
- 把左树信息和右树信息求全集,就是任何一颗子树都需要返回的信息S.
- 递归函数都返回S,每一颗子树都这么要求
- 写代码,在代码中考虑如何把左树的信息和右树的信息整合出整颗树的信息。
2、二叉树按层遍历:
- 借助队列来实现二叉树按层遍历
//定义一个二叉树
public static class Node{
public int value;
public Node left;
public Node right;
public Node(int value){
this.value=value;
}
}
public static void BianLi(Node head){
if(head==null){
return}
Queue<Node> queue=new LinkList<>();
queue.add(head);
while(!queue.isEmpty){
Node cur=queue.poll;
System.out.println(cur.value);
if(cur.left != null){
queue.add(cur.left);
}
if(cur.right != null){
queue.add(cur.right);
}
}
}
3、二叉树先序遍历
public static class Node{
public int value;
public Node left;
public Node right;
public Node(int value){
this.value=value;
}
}
public static void pre(Node head){
if(head == null){
return;
}
System.out.println(head.value);
pre(head.left);
pre(head.right);
}
public static void pre2(head Node){
if(head==null){
return;
}
Stack<Node> stack=new Stack<>();
stack.add(head)
while(!stack.isEmpty(){
Node cur=stack.pop();
if(cur.right != null){
stack.push(cur.right);
}
if(cur.right != null){
stack.push(cur.left);
}
}
}
3、二叉树的中序遍历
public static class Node{
public int value;
public Node left;
public Node right;
public Node(int value){
this.value=value;
}
}
public static void in(Node head){
if(head ==null){
return;
}
in(head.left);
System.out.println(head.value);
in(head.right);
}
public static void in2(Node head){
if(head==null){
return;
}
Stack<Node> stack=new Stack();
while(head != null || !stack.isEmpty()){
if(head!= null){
stack.push(head);
head=head.left;
}else{
stack.pop();
head=head.right;
}
}
]
4、二叉树的后序遍历
public static class Node{
public int value;
public Node left;
public Node right;
public Node(int value){
this.value=this.value;
}
}
public static void pos(Node head){
if(head==null){
return;
}
pos(head.left);
pos(head.right);
System.out.println(head.value);
}
public static void pos1(Node head){
}
5、递归找到最大的子树是搜索二叉树
完全二叉树出现的情况:
1、左树是满的,右树是满的,左高==右高
2、左是完全,右树是满的,左高==右高+1
3、左树是满的,右树是满的,左高==右高+1
4、左树是满的,右树是完全,左高==右高
package com.study.code_4;
import java.util.LinkedList;
public class isBST {
//定义一个二叉树节点
public static class Node{
private int value;
private Node left;
private Node right;
public Node(int value) {
this.value = value;
}
}
public static boolean isCBT1(Node head) {
if (head == null) {
return true;
}
LinkedList<Node> queue = new LinkedList<>();
// 是否遇到过左右两个孩子不双全的节点
boolean leaf = false;
Node l = null;
Node r = null;
queue.add(head);
while (!queue.isEmpty()) {
head = queue.poll();
l = head.left;
r = head.right;
if (
// 如果遇到了不双全的节点之后,又发现当前节点不是叶节点
(leaf && (l != null || r != null)) || (l == null && r != null)
) {
return false;
}
if (l != null) {
queue.add(l);
}
if (r != null) {
queue.add(r);
}
if (l == null || r == null) {
leaf = true;
}
}
return true;
}
public static boolean isCBT2(Node head){
return process(head).isCST;
}
public static class Info{
private boolean isFull;
private boolean isCST;
private int height;
public Info(boolean isFull, boolean isCST, int height) {
this.isFull = isFull;
this.isCST = isCST;
this.height = height;
}
}
public static Info process(Node head){
if (head==null){
return new Info(true,true,0);
}
Info leftInfo=process(head.left);
Info rightInfo=process(head.right);
int height=Math.max(rightInfo.height,leftInfo.height)+1;
boolean isfull=leftInfo.isFull && rightInfo.isFull && leftInfo.height==rightInfo.height;
boolean isCBT=false;
if (leftInfo.isFull && rightInfo.isFull && leftInfo.height==rightInfo.height){
isCBT=true;
}
if (leftInfo.isCST && rightInfo.isFull && leftInfo.height==rightInfo.height+1){
isCBT=true;
}
if (leftInfo.isFull && rightInfo.isFull && leftInfo.height==rightInfo.height+1){
isCBT=true;
}
if (leftInfo.isFull && rightInfo.isCST && leftInfo.height==rightInfo.height){
isCBT=true;
}
return new Info(isfull,isCBT,height);
}
// for test
public static Node generateRandomBST(int maxLevel, int maxValue) {
return generate(1, maxLevel, maxValue);
}
// for test
public static Node generate(int level, int maxLevel, int maxValue) {
if (level > maxLevel || Math.random() < 0.5) {
return null;
}
Node head = new Node((int) (Math.random() * maxValue));
head.left = generate(level + 1, maxLevel, maxValue);
head.right = generate(level + 1, maxLevel, maxValue);
return head;
}
public static void main(String[] args) {
int maxLevel = 5;
int maxValue = 100;
int testTimes = 1000000;
for (int i = 0; i < testTimes; i++) {
Node head = generateRandomBST(maxLevel, maxValue);
if (isCBT1(head) != isCBT2(head)) {
System.out.println("Oops!");
}
}
System.out.println("finish!");
}
}
6、返回a、b节点最低公共祖先
可能出现的情况:
与x无关(x 不是最低汇聚点):
左树有答案
右树有答案
a,b不全
x本身就是a节点,左树和右树发现b
x本身就是b节点,左树和右树发现了a
package com.study.code_4;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class LowestAncestor {
public static class Node{
private int value;
private Node left;
private Node right;
public Node(int value) {
this.value = value;
}
}
public static Node lowestAncestor1(Node head, Node o1, Node o2) {
if (head == null) {
return null;
}
// key的父节点是value
HashMap<Node, Node> parentMap = new HashMap<>();
parentMap.put(head, null);
fillParentMap(head, parentMap);
HashSet<Node> o1Set = new HashSet<>();
Node cur = o1;
o1Set.add(cur);
while (parentMap.get(cur) != null) {
cur = parentMap.get(cur);
o1Set.add(cur);
}
cur = o2;
while (!o1Set.contains(cur)) {
cur = parentMap.get(cur);
}
return cur;
}
public static void fillParentMap(Node head, HashMap<Node, Node> parentMap) {
if (head.left != null) {
parentMap.put(head.left, head);
fillParentMap(head.left, parentMap);
}
if (head.right != null) {
parentMap.put(head.right, head);
fillParentMap(head.right, parentMap);
}
}
public static Node lowestAncestor2(Node head,Node a ,Node b){
return process(head, a, b).ans;
}
public static class Info{
private boolean findA;
private boolean findB;
private Node ans;
public Info(boolean findA, boolean findB, Node ans) {
this.findA = findA;
this.findB = findB;
this.ans = ans;
}
}
public static Info process(Node x,Node a,Node b){
if (x==null){
return new Info(false,false,null);
}
Info leftInfo=process(x.left,a,b);
Info rightInfo=process(x.right,a,b);
boolean findA=(x==a) || leftInfo.findA || rightInfo.findA;
boolean findB=(x==b) || leftInfo.findB || rightInfo.findB;
Node ans=null;
if (leftInfo.ans !=null){
ans=leftInfo.ans;
}else if (rightInfo.ans != null){
ans=rightInfo.ans;
}else{
if (findA && findB){
ans =x;
}
}
return new Info(findA,findB,ans);
}
// for test
public static Node generateRandomBST(int maxLevel, int maxValue) {
return generate(1, maxLevel, maxValue);
}
// for test
public static Node generate(int level, int maxLevel, int maxValue) {
if (level > maxLevel || Math.random() < 0.5) {
return null;
}
Node head = new Node((int) (Math.random() * maxValue));
head.left = generate(level + 1, maxLevel, maxValue);
head.right = generate(level + 1, maxLevel, maxValue);
return head;
}
// for test
public static Node pickRandomOne(Node head) {
if (head == null) {
return null;
}
ArrayList<Node> arr = new ArrayList<>();
fillPrelist(head, arr);
int randomIndex = (int) (Math.random() * arr.size());
return arr.get(randomIndex);
}
// for test
public static void fillPrelist(Node head, ArrayList<Node> arr) {
if (head == null) {
return;
}
arr.add(head);
fillPrelist(head.left, arr);
fillPrelist(head.right, arr);
}
public static void main(String[] args) {
int maxLevel = 4;
int maxValue = 100;
int testTimes = 1000000;
for (int i = 0; i < testTimes; i++) {
Node head = generateRandomBST(maxLevel, maxValue);
Node o1 = pickRandomOne(head);
Node o2 = pickRandomOne(head);
if (lowestAncestor1(head, o1, o2) != lowestAncestor2(head, o1, o2)) {
System.out.println("Oops!");
}
}
System.out.println("finish!");
}
}
7、多叉树
多叉树的原则:
1、选节点
2、直接上下级不能一起请
3、选出最大max值
package com.study.code_4;
import java.util.ArrayList;
import java.util.List;
public class MaxHappy {
public static class Employee{
private int happy;
private List<Employee> nexts;
public Employee(int happy) {
this.happy = happy;
nexts = new ArrayList<>();
}
}
public static int maxHappy1(Employee boss) {
if (boss == null) {
return 0;
}
return process1(boss, false);
}
// 当前来到的节点叫cur,
// up表示cur的上级是否来,
// 该函数含义:
// 如果up为true,表示在cur上级已经确定来,的情况下,cur整棵树能够提供最大的快乐值是多少?
// 如果up为false,表示在cur上级已经确定不来,的情况下,cur整棵树能够提供最大的快乐值是多少?
public static int process1(Employee cur, boolean up) {
if (up) { // 如果cur的上级来的话,cur没得选,只能不来
int ans = 0;
for (Employee next : cur.nexts) {
ans += process1(next, false);
}
return ans;
} else { // 如果cur的上级不来的话,cur可以选,可以来也可以不来
int p1 = cur.happy;
int p2 = 0;
for (Employee next : cur.nexts) {
p1 += process1(next, true);
p2 += process1(next, false);
}
return Math.max(p1, p2);
}
}
public static int maxHappy2(Employee x){
Info result=process(x);
return Math.max(result.yes,result.no);
}
public static class Info{
private int no;
private int yes;
public Info(int no, int yes) {
this.no = no;
this.yes = yes;
}
}
public static Info process(Employee x){
if (x==null){
return new Info(0,0);
}
int no=0;
int yes=x.happy;
for (Employee next:x.nexts){
Info nextInfo=process(next);
no+=Math.max(nextInfo.yes,nextInfo.no);
yes+=nextInfo.yes;
}
return new Info(yes,no);
}
}
二、贪心算法
1、贪心算法是最自然的智慧算法
2、用一种局部最功利的标准,总是做出在当前看来最好的选择。
3、难点在于证明局部最功利的标准可以得到全局最优解。
4、对于贪心算法的学习主要以增加阅历和经验为主。
1、会议室问题
package com.study.code_05;
import java.util.Arrays;
import java.util.Comparator;
public class BestAgree {
public static class Program{
private int start;
private int end;
public Program(int start, int end) {
this.start = start;
this.end = end;
}
}
public static class ProgramComparator implements Comparator<Program>{
@Override
public int compare(Program o1, Program o2) {
return o1.end-o2.end;
}
}
public static int bestArrange2(Program[] programs) {
Arrays.sort(programs,new ProgramComparator());
int timeLine=0;
int result=0;
for (int i = 0; i <programs.length ; i++) {
if (timeLine<=programs[i].start){
result++;
timeLine=programs[i].end;
}
}
return result;
}
}
2、用贪心算法解决输入一个数组返回金条分割的最小代价
利用小根堆
package com.study.code_05;
import java.util.PriorityQueue;
public class LessMoneySplitGold {
public static int lessMoney2(int[] arr){
PriorityQueue<Integer> pq=new PriorityQueue<>();
for (int i = 0; i <arr.length ; i++) {
pq.add(arr[i]);
}
int cur=0;
int sum=0;
while (pq.size()>1){
cur=pq.poll()+pq.poll();
sum+=cur;
pq.add(cur);
}
return sum;
}
}
3、给定字符串str,返回点亮str中所有点亮的位置至少需要几盏灯。
str中全是x和. 需要把字符串中全部的.给点亮,i位置的.可一照亮i+1,i-1位置的.
public static int light(String str){
if(str==null){
return 0;
}
int light=0;
int len=stri.length
int i=0;
while(i<len){
if(str[i]=="x"){
i+=1;
}else{
light++;
if(i+1==len){
break;
}
if(str[i+1]=="x"){
i+=2;
}else {
i+=3;
}
}
}
return light;
}
三、并查集算法
1、并查集code
package com.study.code_05;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class UnitionFind {
public static class Node<V>{
private V value;
public Node(V value) {
this.value = value;
}
}
public static class UnidFind<V>{
public HashMap<V,Node<V>> nodes;
public HashMap<Node<V>,Node<V>> parentMap;
public HashMap<Node<V>,Integer> sizeMap;
public UnidFind(List<V> values) {
nodes = new HashMap<>();
parentMap =new HashMap<>();
sizeMap = new HashMap<>();
for (V cur:values){
Node<V> node = new Node<>(cur);
nodes.put(cur,node);
parentMap.put(node,node);
sizeMap.put(node,1);
}
}
//给一个节点,返回到最上面的节点然后返回
public Node<V> findFather(Node<V> cur){
Stack<Node<V>> path=new Stack<>();
while (cur != parentMap.get(cur)){
path.add(cur);
cur=parentMap.get(cur);
}
while (!path.isEmpty()){
parentMap.put(path.pop(),cur);
}
return cur;
}
public boolean isSameSet(V a,V b){
return findFather(nodes.get(a))==findFather(nodes.get(b));
}
public void unition(V a,V b){
Node<V> pheada=findFather(nodes.get(a));
Node<V> pheadb=findFather(nodes.get(b));
if (pheada != pheadb){
int aSetSize=sizeMap.get(pheada);
int bSetSize=sizeMap.get(pheadb);
Node<V> big=aSetSize>bSetSize?pheada:pheadb;
Node<V> small=big==pheada?pheadb:pheada;
parentMap.put(small,big);
sizeMap.put(big,aSetSize+bSetSize);
sizeMap.remove(small);
}
}
public int sets(){
return sizeMap.size();
}
}
}
2、有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-provinces
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
public static class findCircleNum{
public static int findCircleNum(int[][] M){
int N=M.length;
UnitionFind un=new UnitionFind(N);
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
if(M[i][j]==1){
un.unition(i,j);
}
}
}
return un.sets();
}
public static class UnitionFind{
// 辅助结构
private int[] help;
// parent[i] = k : i的父亲是k
private int[] parent;
// size[i] = k : 如果i是代表节点,size[i]才有意义,否则无意义
// i所在的集合大小是多少
private int[] size;
//一共多少个集合
private int sets;
public UnitiopnFind(int N){
help=new int[N];
parent=new int[N];
size=new int[N];
sets=N;
for(int i ;i <N;i++){
parent[i]=i;
size[i]=1;
}
public static find(int i){
int hi=0;
while(i != parent[i]){
help[hi++]==i;
i=parent[i];
}
for(hi--;hi>0;hi--){
parent[help[hi]]=i;
}
return i;
}
public static void unition(int i,int j){
int findi=find(i);
int findj=find(j);
while(findi != findj){
if(size[findj]>size[findi]){
parent[findi]=findj;
size[findi] +=size[findj];
}else{
parent[findj]=findi;
size[findj] +=size[findi];
}
sets--;
}
}
public int sets(){
return sets;
}
}
}
}
3、并集查询
题目链接:https://leetcode.com/problems/number-of-islands-ii/
时间复杂度 O(m*n)+O(k)
public satic class NumberOfIslands{
public static List<Integer> numberofIsLands(int m,int n,int[][] postions){
UnitionFind un=new UnitionFind(m,n);
List<Integer> ans=new ArrayList<>();
for(int[] postion:postions){
ans.add(un.connect(ponstion[0],ponstion[1]));
}
return ans;
}
public static UnitionFind{
private int[] parent;
private int[] help;
private int[] size;
private int col;
private int row;
private int sets;
public UnitionFind(int r,int c){
int col=c;
int row=r;
int len=col*row;
parent=new int[len];
help=new int[len];
size=new size[len];
sets=0;
}
public int index(int r,int c){
return r*col+c;
}
public int find(int i){
int hi=0;
while(i != parent[i]){
help[hi++]=i;
i=parent[i];
}
for(hi--;hi>0;hi--){
parent[help[hi]]=i;
}
return i;
}
public void unition(int r1,int c1,int r2,int c2){
if(r1<0 || r1==row || c1<0 || c1==col || r2<0 || r2==row || c2<0 || c2==col){
return;
}
int i1=index(r1,c1);
int i2=index(r2,c2);
if(size[i1]==0 || size[i2]==0){
return;
}
int find1=find(i1);
int find2=find(i2);
if(find1 != find1){
if(size(find1)>size(find2))){
parent[find2]=find1;
size[find1]+=size[find2];
}else{
parent[find1]=find2;
size[find2]+=size[find1];
}
sets--;
}
}
public int connect(int r,int c){
int i=index(r,c);
if(size[i]==0){
parent[i]=i;
size[i]=1;
sets++;
unition(r-1,c,r,c);
unition(r,c,r+1,c);
unition(r,c-1,r,c);
unition(r,c,r,c+1);
}
return sets;
}
}
}
解2:
// 课上讲的如果m*n比较大,会经历很重的初始化,而k比较小,怎么优化的方法
public static List<Integer> numIslands22(int m, int n, int[][] positions) {
UnionFind2 uf = new UnionFind2();
List<Integer> ans = new ArrayList<>();
for (int[] position : positions) {
ans.add(uf.connect(position[0], position[1]));
}
return ans;
}
public static class UnionFind2 {
private HashMap<String, String> parent;
private HashMap<String, Integer> size;
private ArrayList<String> help;
private int sets;
public UnionFind2() {
parent = new HashMap<>();
size = new HashMap<>();
help = new ArrayList<>();
sets = 0;
}
private String find(String cur) {
while (!cur.equals(parent.get(cur))) {
help.add(cur);
cur = parent.get(cur);
}
for (String str : help) {
parent.put(str, cur);
}
help.clear();
return cur;
}
private void union(String s1, String s2) {
if (parent.containsKey(s1) && parent.containsKey(s2)) {
String f1 = find(s1);
String f2 = find(s2);
if (!f1.equals(f2)) {
int size1 = size.get(f1);
int size2 = size.get(f2);
String big = size1 >= size2 ? f1 : f2;
String small = big == f1 ? f2 : f1;
parent.put(small, big);
size.put(big, size1 + size2);
sets--;
}
}
}
public int connect(int r, int c) {
String key = String.valueOf(r) + "_" + String.valueOf(c);
if (!parent.containsKey(key)) {
parent.put(key, key);
size.put(key, 1);
sets++;
String up = String.valueOf(r - 1) + "_" + String.valueOf(c);
String down = String.valueOf(r + 1) + "_" + String.valueOf(c);
String left = String.valueOf(r) + "_" + String.valueOf(c - 1);
String right = String.valueOf(r) + "_" + String.valueOf(c + 1);
union(up, key);
union(down, key);
union(left, key);
union(right, key);
}
return sets;
}
四、图
1、定义点的结构
public class Node{
private int value;
private int in;
private int out;
private ArrayList<Node> nexts;
private ArrayList<Edge> edges;
public Node(int value){
this.value=value;
this.in=0;
this.out=0;
nexts=new ArrayList<>();
edges=new ArrayList<>();
}
}
public class Edge{
private int weight;
private Node from;
private Node to;
public Edge(int weight,Node from ,Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
public class Graph{
public HashMap<Integer,Node> nodes;
public HashSet<Edge> edges;
public Graph(){
nodes=new HashMap<>();
edges=new HashSet<>();
}
}
图:
1、由点的集合和边的集构成。
2、虽然存在有向图和无向图的概念,但实际上都可以用有向图来表达。
3、边上可能带权值。
2、从节点出发进行宽度优先遍历
public static void bfs(Node start){
if(start==null){
return;
}
Queue<Node> queue=new LinkList<>();
HashSet<Node> set=new HashSet<>();
queue.add(start);
set.add(start);
while(!queue.isEmpty){
Node curs=queue.poll();
System.out.println(curs.value);
for(Node cur:curs.nexts){
if(!set.container(cur)){
queue.add(cur);
set.add(cur);
}
}
}
}
4、深度遍历
public static void dfs(Node start){
if (start==null){
return;
}
Stack<Node> stack=new Stack<>();
HashSet<Node> hashSet=new HashSet<>();
stack.add(start);
hashSet.add(start);
System.out.println(start.value);
while (!stack.isEmpty()){
Node curs=stack.pop();
for (Node cur:curs.nexts){
if (!hashSet.contains(cur)){
stack.push(curs);
stack.push(cur);
hashSet.add(cur);
System.out.println(cur.value);
break;
}
}
}
}
5、图的拓扑排序算法
思路:借助队列和hashMap
1、将所有节点的入度都放到map中,
2、将所有入度为0的节点都放在队列中
3、然后从队列中弹出,加入列表里。
public static List<Node> sortGraph(Graph graph){
HashMap<Node,Integer> hashmap=new HashMap<>();
Queue<Node> queue=new LinkList<>();
for(Node node:graph.nodes.values){
hashmap.put(node,node.in);
if(node.in==0){
queue.add(node);
}
}
List<Node> result=new ArrayList<>();
while(!queue.isEmpty){
Node cur=queue.poll();
result.add(cur);
for(Node next:cur.nexts){
hashMap.put(next,next.in-1);
if(hashmap.get(next)==0){
queue.add(next);
}
}
}
return result;
}
6、最小生成树算法
1、可以从任意节点出发来寻找最小生成树。
2、某个点被加入到被选取的点中后,解锁这个点出发的所有新的边。
3、在所有解锁的边中选最小的边,然后看看这个边会不会形成环
4、如果会,不要当前边,继续靠察剩下解锁的边中,最小的边。
5、如果不会,要当前边,将该边的指向点加入到被选取的点中。
6、当所有点都被选取,最小生成树就得到了。
public static class MyCompator implements Comparator<Edge>{
@Override
public int compare(Edge o1, Edge o2) {
return o1.weight-o2.weight;
}
}
public static Set<Edge> prim(Graph graph){
// 解锁的边进入小根堆
PriorityQueue<Edge> priorityQueue=new PriorityQueue<>(new MyCompator());
// 解锁的边进入小根堆
HashSet<Node> hashSet=new HashSet<>();
Set<Edge> result=new HashSet<>();// 依次挑选的的边在result里
for (Node node:graph.nodes.values()){
if (!hashSet.contains(node)){
hashSet.add(node);
for(Edge edge:node.edges){
priorityQueue.add(edge);
}
while (!priorityQueue.isEmpty()){
Edge cur=priorityQueue.poll();
Node toNode=cur.to;
if (!hashSet.contains(toNode)){
hashSet.add(toNode);
result.add(cur);
}
for (Edge edge : toNode.edges){
priorityQueue.add(edge);
}
}
}
}
return result;
}
五、暴力递归
暴力递归是常识
1、把问题转化为规模缩小了的同类问题的字问题
2、有明确的不需要进行递归的条件
3、有当得到了子问题的结果之后的决策过程
4、不记录每一个子问题的解
1、打印n层汉诺塔从最左边移动到最右边的全部过程
public static class Hanota{
public static void LeftToRight(int n){
if(n==1){
System.out.pringln("Move 1 from left to right");
return;
}
leftToMid(n-1);
System.out.println("move "+n+" from mid to right");
midToRight(n-1);
}
public static void midToRight(int n){
if(n==1){
System.out.println("move 1 from mid to right");
return;
}
midToLeft(n-1);
System.out.pringln("move "+n+" from mid to right ");
leftToRight(n-1);
}
public static 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 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);
}
public 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);
}
public 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");
leftToMid(n-1);
}
}
方法2:
public static hannoi(int n){
hanioi2(n,"left","right","mid)
}
public static hanio2(int n,String from,String to,String other){
if(n==1){
System.out.pringln("move 1 from "+from+" to "+to);
}
hanio2(n-1,from,other,to);
System.out.println("move"+n+"from "+from+" to "+to);
hanio2(n-1,other,to,from);
}
2、打印一个字符串的全部子序列
// str 固定参数
// 来到了str[index]字符,index是位置
// str[0..index-1]已经走过了!之前的决定,都在path上
// 之前的决定已经不能改变了,就是path
// str[index....]还能决定,之前已经确定,而后面还能自由选择的话,
// 把所有生成的子序列,放入到ans里去
public satic List<String> pringSubqueue(String str){
char[] s=str.toCharArray();
List<String> ans=new ArrayList<>();
String payh="";
process();
}
public static void Process(char[] str,int index,List<String> ans,String path){
if(str.length==index){
ans.add(path);
return;
}
process(str,index+1,ans,path);
process(str,index+1,ans,path+String.valueOf(str[index]));
}
3、打印一个字符串的全部子序列,要求不要出现重复字面值的子序列
public static List<String> pringSubQueue(String str){
char[] s=str.toCharArray();
String path="";
Set<String> result=new HashSet<>();
process(s,0,result,path);
List<String> ans=new ArrayList<>();
for(String cur:result){
ans.add(cur);
}
return ans;
}
public static void process(char[] str,int index,Set<String> result,String path){
if(String.length==index){
result.add(path);
return;
}
process(str,index+1,result,path);
process(str,index+1,result,path+String.valueOf(str[index]))
}
4、打印一个字符串的全部排列
public static List<String> printAll(String s){
List<String> ans=new ArrayList<>();
if(s==null || s.length()==0){
return ans;
}
char[] str=s.toCharArray();
}
public static void g(char[] str,int index,ArrayList<String> ans){
if(str.length==index){
ans.add(String.valueOf(str));
return;
}else{
for(int i=index,i<str.length,i++){
swap(str,index,i);
g2(str,index+1,ans);
swap(str,index,i);
}
}
}
//去重的全排列
public static void g3(char[] str,int index,List<String> ans){
if(index==str.length){
ans.add(String.valueOf(str));
return;
}else{
boolean[] isVisit=new boolean[256];
for(int i=index,i<str.length,i++){
if(!isVisit(str[i])){
isVisit(str[i])=true;
swap(str,index,i);
g3(str,index+1,ans);
swap(str,index,i);
}
}
}
}
public static void swap(char[] str,int index1,int index2){
char temp=str[index1];
str[index1]=str[index2];
str[index2]=temp;
}