1.递归问题
1.1计算阶乘
packageinterview.recursion;importjava.util.Scanner;public classFact {public static voidmain(String[] args) {
System.out.println("请输入n的值:");
Scanner in= newScanner(System.in);int n =in.nextInt();int num =fact(n);
System.out.println(n+ "的阶乘为:" +num);
}public static int fact(intn) {if (n == 1) {return 1;
}return n * fact(n - 1);
}
}
1.2计算斐波那契数列
Fibonacci sequence:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ……
packageinterview.recursion;importjava.util.Scanner;public classFib {public static int fib(intn) {if (n == 0) {return 0;
}else if (n == 1) {return 1;
}else{return fib(n - 1) + fib(n - 2);
}
}public static voidmain(String[] args) {
System.out.println("请输入n的值:");
Scanner in= newScanner(System.in);int n =in.nextInt();int num =fib(n);
System.out.println("第" + n + "个值的fib为:" + +num);
}
}
1.3计算最大公约数(辗转相除法)
packageinterview.recursion;importjava.util.Scanner;public classGcd {public static int gcd(int max, intmin) {if (min == 0) {returnmax;
}else{return gcd(min, max %min);
}
}public static voidmain(String[] args) {
System.out.println("请输入max的值:");
Scanner in= newScanner(System.in);int max =in.nextInt();
System.out.println("请输入min的值:");int min =in.nextInt();int num =gcd(max, min);
System.out.println(max+ "和" + min + "的最大公约数为:" +num);
}
}
1.4汉诺塔问题(递归)
问题描述
三个柱子,起初有若干个按大小关系顺序安放的盘子,需要全部移动到另外一个柱子上。移动规则:在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
移动次数: f(n)=2n -1
解法思路
使用递归算法进行处理。
汉诺塔的算法大概有3个步骤:
(1)把a上的n-1个盘通过c移动到b。
(2)把a上的最下面的盘移到c。
(3)因为n-1个盘全在b上了,所以把b当做a重复以上步骤就好了。
在网上找到一个3阶的汉诺塔递归过程示意图,参考一下。
packagecn.jxufe.ch06_hanoitowers;public classHanoiTowers {/*** 汉诺塔问题:所有的盘子,刚开始都在塔座A上,要求将所有的盘子从塔座A移动到塔座C,每次只能移动一个盘子,且
* 任何盘子不能放在比自己小的盘子上。
*
*@paramtopN:移动的盘子数
*@paramfrom:从哪个塔座开始
*@paraminter:中间塔座
*@paramto;目标塔座*/
public static void doTower(int topN, char from, char inter, charto) {if (topN == 1) {
System.out.println("盘子1,从" + from + "塔座到" + to + "塔座");return;
}else{
doTower(topN- 1, from, to, inter);
System.out.println("盘子" + topN + ",从" + from + "塔座到" + to + "塔座");
doTower(topN- 1, inter, from, to);
}
}
}
packagecn.jxufe.ch06_hanoitowers;public classTestHanoiTowers {public static voidmain(String[] args) {
HanoiTowers.doTower(4,'A','B','C');
}
}
1.5瓶盖问题
packagetest;/** 描述:每 3 个可乐盖可兑换 1 瓶子可乐,求买 n 瓶可乐最终可获得的可乐瓶子数。*/
importjava.util.Scanner;public classT03 {public static int times = 1;public static voidmain(String[] args) {
Scanner input= newScanner(System.in);
System.out.print("输入购买的可乐数:");
times= 1;int j =input.nextInt();int i =func(j);
System.out.println("--------------------------");
System.out.println("总共可获得 " + i + " 瓶\n\n");
}public static int func(inti) {if (i < 3) {
System.out.println("最终剩下 " + i + " 个瓶盖,不足以兑换");returni;
}else{
System.out.println("第 " + times++ + " 次兑换," + "本次兑换总共有 " + i + " 个瓶盖,用 " + (i - i % 3) + " 个瓶盖换了 " + i / 3
+ " 瓶可乐,剩余 " + i % 3 + " 个瓶盖可用于下次兑换");return ((i - i % 3) + func(i / 3 + i % 3));
}
}
}
1.6走楼梯
题目描述:
一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少总跳法。
思路:当n大于2的时候,每次可以选择走2级也可以选择走1级,所有都有两种方案。即f(n-1)+f(n-2)
packageinterview.recursion;importjava.util.Scanner;public classStairs {public static int solve(intn) {if (n == 1) {return 1;
}else if (n == 2) {return 2;
}else{return solve(n - 1) + solve(n - 2);
}
}public static voidmain(String[] args) {
System.out.println("请输入n的值:");
Scanner in= newScanner(System.in);int n =in.nextInt();int num =solve(n);
System.out.println("总共有" + num + "种走法");
}
}
2.二叉树
2.1插入和查找
packagecn.jxufe.ch07_tree;/*** 二叉树节点*/
public classNode {//数据项
public intdata;publicString sdata;publicNode leftChild;publicNode rightChild;public Node(intdata,String sdata) {this.data =data;this.sdata =sdata;
}
}
packagecn.jxufe.ch07_tree;/*** 二叉树*/
public classTree {//根节点
publicNode root;/*** 插入节点*/
public void insert(intvalue,String sdata) {//封装节点
Node newNode = newNode(value,sdata);//引用当前节点
Node current =root;//引用父节点
Node parent;//如果root为null,也就是第一次插入的节点
if (root == null) {
root=newNode;return;
}else{while (true) {//父节点指向当前节点
parent =current;//如果当前节点指向的数据,比插入的要大,则向左走
if (value
current=current.leftChild;if (current == null) {
parent.leftChild=newNode;return;
}
}else{
current=current.rightChild;if (current == null) {
parent.rightChild=newNode;return;
}
}
}
}
}/*** 查找节点*/
public Node find(intvalue) {//引用当前节点,从根节点开始
Node current =root;//只要查找的值,不等于当前节点的值
while (current.data !=value) {//比较查找值,与当前节点值的大小
if (current.data >value) {
current=current.leftChild;
}else{
current=current.rightChild;
}//如果查找不到
if (current == null) {return null;
}
}returncurrent;
}/*** 删除节点*/
public void delete(intvalue) {
}
}
packagecn.jxufe.ch07_tree;public classTestTree {public static voidmain(String[] args) {
Tree tree= newTree();
tree.insert(10, "zhangsan");
tree.insert(20, "lisi");
tree.insert(3, "wangwu");
tree.insert(14, "zhaoliu");
tree.insert(76, "zhouqi");
System.out.println(tree.root.data);
System.out.println(tree.root.leftChild.data);
System.out.println(tree.root.rightChild.data);
System.out.println(tree.root.rightChild.leftChild.data);
System.out.println(tree.root.rightChild.rightChild.data);
Node node= tree.find(20);
System.out.println(node.data+ "," +node.sdata);
System.out.println(node.rightChild.data+ "," +node.rightChild.sdata);
}
}
2.2遍历二叉树
packagecn.jxufe.ch07_tree;/*** 二叉树节点*/
public classNode {//数据项
public intdata;publicString sdata;publicNode leftChild;publicNode rightChild;public Node(intdata,String sdata) {this.data =data;this.sdata =sdata;
}
}
packagecn.jxufe.ch07_tree;/*** 二叉树*/
public classTree {//根节点
publicNode root;/*** 插入节点*/
public void insert(intvalue, String sdata) {//封装节点
Node newNode = newNode(value, sdata);//引用当前节点
Node current =root;//引用父节点
Node parent;//如果root为null,也就是第一次插入的节点
if (root == null) {
root=newNode;return;
}else{while (true) {//父节点指向当前节点
parent =current;//如果当前节点指向的数据,比插入的要大,则向左走
if (value
current=current.leftChild;if (current == null) {
parent.leftChild=newNode;return;
}
}else{
current=current.rightChild;if (current == null) {
parent.rightChild=newNode;return;
}
}
}
}
}/*** 查找节点*/
public Node find(intvalue) {//引用当前节点,从根节点开始
Node current =root;//只要查找的值,不等于当前节点的值
while (current.data !=value) {//比较查找值,与当前节点值的大小
if (current.data >value) {
current=current.leftChild;
}else{
current=current.rightChild;
}//如果查找不到
if (current == null) {return null;
}
}returncurrent;
}/*** 删除节点*/
public void delete(intvalue) {
}/*** 前序遍历*/
public voidfrontOrder(Node localNode) {if (localNode != null) {//访问根节点
System.out.print(localNode.data + ":" + localNode.sdata + " ");//前序遍历左子树
frontOrder(localNode.leftChild);//前序遍历右子树
frontOrder(localNode.rightChild);
}
}/*** 中序遍历*/
public voidinOrder(Node localNode) {if (localNode != null) {//中序遍历左子树
inOrder(localNode.leftChild);//访问根节点
System.out.print(localNode.data + "," + localNode.sdata + " ");//中序遍历右子树
inOrder(localNode.rightChild);
}
}/*** 后序遍历*/
public voidafterOrder(Node localNode) {if (localNode != null) {//后序遍历左子树
afterOrder(localNode.leftChild);//后序遍历右子树
afterOrder(localNode.rightChild);//访问根节点
System.out.print(localNode.data + "," + localNode.sdata + " ");
}
}
}
packagecn.jxufe.ch07_tree;public classTestTree {public static voidmain(String[] args) {
Tree tree= newTree();
tree.insert(10, "zhangsan");
tree.insert(20, "lisi");
tree.insert(3, "wangwu");
tree.insert(14, "zhaoliu");
tree.insert(76, "zhouqi");
tree.insert(13, "zhuba");
System.out.println("前序遍历:");
tree.frontOrder(tree.root);
System.out.println();
System.out.println("中序遍历:");
tree.inOrder(tree.root);
System.out.println();
System.out.println("后序遍历:");
tree.afterOrder(tree.root);
}
}
2.3删除二叉树节点
packageinterview;public classTree {privateNode root;public void insertNode(intdata, String sdata) {
Node newNode= newNode(data, sdata);//引用当前节点
Node current =root;
Node parent;//如果root为null,也就是第一次插入
if (root == null) {
root=newNode;
}else{while (true) {
parent=current;//如果当前节点指向的数据,比插入的节点数据要大,则向左走
if (data
current=current.leftChildNode;if (current == null) {
parent.leftChildNode=newNode;return;
}
}else{
current=current.rightChildNode;if (current == null) {
parent.rightChildNode=newNode;return;
}
}
}
}
}public Node findNode(intvalue) {
Node current=root;while (current.data !=value) {if (current.data >value) {
current=current.leftChildNode;
}else{
current=current.rightChildNode;
}if (current == null) {return null;
}
}returncurrent;
}public voidfontOrder(Node root) {if (root != null) {
System.out.println(root.data);
fontOrder(root.leftChildNode);
fontOrder(root.rightChildNode);
}
}publicNode getSuccessor(Node delNode) {
Node successor=delNode;
Node successorParent=delNode;
Node current=delNode.rightChildNode;while (current != null) {
successorParent=successor;
successor=current;
current=current.leftChildNode;
}if(successor !=delNode.rightChildNode) {
successorParent.leftChildNode=successor.rightChildNode;
successor.rightChildNode=delNode.rightChildNode;
}returnsuccessor;
}public boolean deleteNode(intvalue) {//引用当前节点为根节点
Node current =root;//引用当前节点的父节点
Node parent =root;//是否为左子树
boolean isLeftchild = true;//查找
while (current.data !=value) {
parent=current;//比较
if (current.data >value) {
current=current.leftChildNode;
isLeftchild= true;
}else{
current=current.rightChildNode;
isLeftchild= false;
}if (current == null) {return false;
}
}//删除
if (current.leftChildNode == null && current.rightChildNode == null) {//1. 删除的节点为叶子节点
if (current ==root) {
root= null;
}else if (isLeftchild) {//如果它是父节点的左子节点
parent.leftChildNode = null;
}else{
parent.rightChildNode= null;
}
}else if (current.rightChildNode == null) { //2. 该节点有一个子节点,且为左子节点
if (current ==root) {
root=current.leftChildNode;
}else if(isLeftchild) {
parent.leftChildNode=current.leftChildNode;
}else{
parent.rightChildNode=current.leftChildNode;
}
}else if (current.leftChildNode == null) { //该节点只有一个节点,且为右子节点
if (current ==root) {
root=current.rightChildNode;
}else if(isLeftchild) {
parent.leftChildNode=current.rightChildNode;
}else{
parent.rightChildNode=current.rightChildNode;
}
}else{
Node successor= getSuccessor(current);//查找中序后继节点
if(current == root) { //以下是完成替换功能
root =successor;
}else if(isLeftchild) {
parent.leftChildNode=successor;
}else{
parent.rightChildNode=successor;
}
successor.leftChildNode=current.leftChildNode;
}return true;
}public static voidmain(String[] args) {
Tree tree= newTree();
tree.insertNode(10, "zhangsan");
tree.insertNode(20, "lisi");
tree.insertNode(3, "wangwu");
tree.insertNode(14, "zhaoliu");
tree.insertNode(76, "zhouqi");
tree.insertNode(5, "niaho");//System.out.println(tree.root.data);//System.out.println(tree.root.leftChildNode.data);//System.out.println(tree.root.rightChildNode.data);//System.out.println(tree.root.rightChildNode.leftChildNode.data);//System.out.println(tree.root.rightChildNode.rightChildNode.data);//Node node = tree.findNode(20);//System.out.println(node.data + "," + node.sdata);//System.out.println(node.rightChildNode.data + "," +//node.rightChildNode.sdata);
tree.fontOrder(tree.root);
tree.deleteNode(3);
System.out.println("--------------------");
tree.fontOrder(tree.root);
tree.deleteNode(20);
System.out.println("------------------------");
tree.fontOrder(tree.root);
}
}classNode {//数据域
public intdata;publicString sdata;//指针域
publicNode leftChildNode;publicNode rightChildNode;public Node(intdata, String sdata) {//TODO Auto-generated constructor stub
this.data =data;this.sdata =sdata;
}
}
2.4根据中序和后序,求前序遍历
packageexam;importjava.util.Arrays;public classMain {public static voidmain(String[] args) {//TODO Auto-generated method stub//Scanner sc = new Scanner(System.in);//String in = sc.nextLine();
String in = "dgbaechf";char[] inArray =in.toCharArray();//String last = sc.nextLine();
String last = "gbdehfca";char[] lastArray =last.toCharArray();//System.out.println(Arrays.toString(preArray));//System.out.println(Arrays.toString(inArray));
Node node =buildTree(inArray, lastArray);
frontOrder(node);
}public static Node buildTree(char[] inorder, char[] postorder) {if (inorder == null || postorder == null || inorder.length == 0 || postorder.length == 0) {return null;
}//将后序遍历的最后一个节点取出为根
Node root = new Node(postorder[postorder.length - 1]);int i = 0;//记录中序遍历根的位置
for (; i < inorder.length; i++) {if (postorder[postorder.length - 1] ==inorder[i]) {break;
}
}//构造左子树
char[] leftIn = Arrays.copyOfRange(inorder, 0, i);char[] leftPost = Arrays.copyOfRange(postorder, 0, i);//构造右子树
char[] rightIn = Arrays.copyOfRange(inorder, i + 1, inorder.length);char[] rightPost = Arrays.copyOfRange(postorder, i, postorder.length - 1);//左子树
root.leftChild =buildTree(leftIn, leftPost);//右子树
root.rightChild =buildTree(rightIn, rightPost);returnroot;
}/*** 前序遍历*/
public static voidfrontOrder(Node localNode) {if (localNode != null) {//访问根节点
System.out.print(localNode.data + " ");//前序遍历左子树
frontOrder(localNode.leftChild);//前序遍历右子树
frontOrder(localNode.rightChild);
}
}
}/*** 二叉树节点*/
classNode {//数据项
public chardata;publicNode leftChild;publicNode rightChild;public Node(chardata) {this.data =data;
}
}
2.5二叉树高度
packagedatastruct.t04tree;/*** 二叉树节点
**/
public classNode {public intdata;publicNode leftChild;publicNode rightChild;public Node(intdata) {this.data =data;
}public voidsetLeftChild(Node leftChild) {this.leftChild =leftChild;
}public voidsetRightChild(Node rightChild) {this.rightChild =rightChild;
}public static Node createNode(intdata) {
Node node= newNode(data);
node.leftChild= node.rightChild = null;returnnode;
}public static voidsetChild(Node node, Node leftChild, Node rightChild) {
node.setLeftChild(leftChild);
node.setRightChild(rightChild);
}
}
packagedatastruct.t04tree;public classBiTree {public static intgetTreeHeight(Node root) {if (root == null) {return 0;
}else{int leftHeight =getTreeHeight(root.leftChild);int rightHeight =getTreeHeight(root.rightChild);return Math.max(leftHeight, rightHeight) + 1;
}
}public static voidmain(String[] args) {//快速构建一棵二叉树
Node root = Node.createNode(1);
Node node2= Node.createNode(2);
Node node3= Node.createNode(3);
Node node4= Node.createNode(4);
Node node5= Node.createNode(5);
Node node6= Node.createNode(6);
Node node7= Node.createNode(7);
Node node8= Node.createNode(8);
Node.setChild(root, node2, node3);
Node.setChild(node2, node4, node5);
Node.setChild(node3,null, node7);
Node.setChild(node4,null, node8);
Node.setChild(node5, node6,null);//树的高度
int height =getTreeHeight(root);
System.out.print("树的高度为:");
System.out.println(height);
}
}
2.6表达式树的输出与求值
表达式树的特征:叶节点是运算数,非叶节点一定是运算符
输入格式:
第一行给出节点的个数N,每个节点的编号为0 ~ N-1
接下来N行每行分别给出:
该节点的编号、该节点的操作数/操作符、该节点的左孩子编号、右孩子编号(-1表示NULL)
输出格式:
第一行输出该表达式树的中缀表达式,该用括号的地方需要用括号括起来。
第二行输出该表达式树的前缀表达式。
第二行输出该表达式树的后缀表达式。
第四行输出该表达式树的计算结果,保留两位小数。
样例输入:
11
0 - 1 2
1 + 3 4
2 / 5 6
3 4 -1 -1
4 * 7 8
5 6 -1 -1
6 3 -1 -1
7 1 -1 -1
8 - 9 10
9 5 -1 -1
10 2 -1 -1
样例输出:
(4+(1*(5-2)))-(6/3)- + 4 * 1 - 5 2 / 6 3
4 1 5 2 - * + 6 3 / -
5.00
packagedatastruct.t04tree.exptree;public classNode {chardata;
Node leftChild;
Node rightChild;
}
packagedatastruct.t04tree.exptree;importjava.util.Scanner;public classExpTree {//中缀表达式
public static void inOrder(Node root, intlayer) {if (root == null)return;if (root.leftChild == null && root.rightChild == null) {//叶结点是操作数,直接输出,不加括号
System.out.print(root.data + " ");
}else{//非叶节点是操作符,需加括号(第0层根节点除外)
if (layer > 0) {
System.out.print("(");
}
inOrder(root.leftChild, layer+ 1);
System.out.print(root.data+ " ");
inOrder(root.rightChild, layer+ 1);if (layer > 0) {
System.out.print(")");
}
}
}//前缀表达式
public static voidpreOrder(Node root) {if (root == null)return;
System.out.print(root.data+ " ");
preOrder(root.leftChild);
preOrder(root.rightChild);
}//后缀表达式
public static voidpostOrder(Node root) {if (root == null)return;
postOrder(root.leftChild);
postOrder(root.rightChild);
System.out.print(root.data+ " ");
}public static doublegetExpTree(Node root) {if (root == null) {return 0;
}if (root.leftChild == null && root.rightChild == null) {//叶节点,节点存放的是 操作数
return root.data - '0'; //将字符转换成数字
}//非叶结点,节点存放的是 操作符
double a =getExpTree(root.leftChild);double b =getExpTree(root.rightChild);returncal(a, b, root.data);
}public static double cal(double a, double b, charop) {switch(op) {case '+':return a +b;case '-':return a -b;case '*':return a *b;case '/':return a /b;default:return 0;
}
}public static voidmain(String[] args) {
Scanner input= newScanner(System.in);
System.out.println("请输入节点的个数");int N =input.nextInt();
Node[] nodes= newNode[N];for (int i = 0; i < N; i++) {
nodes[i]= newNode();
}
System.out.println("请输入index,data,l,r");for (int i = 0; i < N; i++) {int index =input.nextInt();char data = input.next().charAt(0);int l =input.nextInt();int r =input.nextInt();
nodes[index].data=data;
nodes[index].leftChild= (l != -1 ? nodes[l] : null);
nodes[index].rightChild= (r != -1 ? nodes[r] : null);
}
Node root= nodes[0];
inOrder(root,0);
System.out.println();
preOrder(root);
System.out.println();
postOrder(root);
System.out.println();double value =getExpTree(root);
System.out.println(value);
}
}
2.7求二叉树指定节点所在层数(假设根节点的层数为1)
1.方法1
packagedatastruct.t04tree.layer;classNode {intdata;
Node leftChild;
Node rightChild;public Node(intdata) {this.data =data;
}public voidsetChild(Node leftChild, Node rightChild) {this.leftChild =leftChild;this.rightChild =rightChild;
}
}public classNodeLayer {static int layer = 0;static boolean flag = false;//flag标记可用于提前快速结束递归的执行
public static void getNodeLayer(Node root, intvalue) {if (root == null)return;if(flag)return;
layer++;if (root.data ==value) {
System.out.println(layer);
flag= true;return;
}
getNodeLayer(root.leftChild, value);
getNodeLayer(root.rightChild, value);
layer--;
}public static voidmain(String[] args) {
Node root= new Node(1);
Node node2= new Node(2);
Node node3= new Node(3);
Node node4= new Node(4);
Node node5= new Node(5);
Node node6= new Node(6);
Node node7= new Node(7);
Node node8= new Node(8);
root.setChild(node2, node3);
node2.setChild(node4, node5);
node3.setChild(null, node6);
node5.setChild(node7,null);
node7.setChild(null, node8);int value = 7;
getNodeLayer(root, value);
}
}
2.方法2
packagedatastruct.t04tree.layer;classNode {intdata;
Node leftChild;
Node rightChild;public Node(intdata) {this.data =data;
}public voidsetChild(Node leftChild, Node rightChild) {this.leftChild =leftChild;this.rightChild =rightChild;
}
}public classNodeLayer {
static boolean flag = false;public static void getNodeLayer(Node root, int value, intlayer) {if (root == null)return;if(flag)return;if (root.data ==value) {
System.out.println(layer);
flag= true;return;
}
getNodeLayer(root.leftChild, value, layer+ 1);
getNodeLayer(root.rightChild, value, layer+ 1);
}public static voidmain(String[] args) {
Node root= new Node(1);
Node node2= new Node(2);
Node node3= new Node(3);
Node node4= new Node(4);
Node node5= new Node(5);
Node node6= new Node(6);
Node node7= new Node(7);
Node node8= new Node(8);
root.setChild(node2, node3);
node2.setChild(node4, node5);
node3.setChild(null, node6);
node5.setChild(node7,null);
node7.setChild(null, node8);int value = 7;
getNodeLayer(root, value, 1);
}
}
2.8求某节点到根节点的路径
对于如下二叉树,节点 7 位于第 4 层,其到跟节点的路径为 1 2 5 7
packagedatastruct.t04tree.path;importjava.util.Stack;classNode {intdata;
Node leftChild;
Node rightChild;public Node(intdata) {this.data =data;
}public voidsetChild(Node leftChild, Node rightChild) {this.leftChild =leftChild;this.rightChild =rightChild;
}
}public classTreePath {static Stack path = new Stack<>();static boolean flag = false;public static void getNodePath(Node root, intvalue) {if (root == null)return;if(flag)return;
path.add(root.data);if (root.data ==value) {for(Integer integer : path) {
System.out.print(integer+ " ");
}
flag= true;return;
}
getNodePath(root.leftChild, value);
getNodePath(root.rightChild, value);
path.pop();
}public static voidmain(String[] args) {
Node root= new Node(1);
Node node2= new Node(2);
Node node3= new Node(3);
Node node4= new Node(4);
Node node5= new Node(5);
Node node6= new Node(6);
Node node7= new Node(7);
Node node8= new Node(8);
root.setChild(node2, node3);
node2.setChild(node4, node5);
node3.setChild(null, node6);
node5.setChild(node7,null);
node7.setChild(null, node8);int value = 7;
getNodePath(root, value);
}
}
2.9全排列问题
输出数字1~N所能组成的所有全排列
packagedatastruct.t04tree.permutation;importjava.util.Stack;public classPermutation {public static int MAXN = 10;static boolean[] isUsed = new boolean[MAXN];static Stack nums = new Stack<>();static intN;/***@paramindex
* 表示第几层*/
public static void DFS(intindex) {if (index >=N) {for(Integer i : nums)
System.out.print(i+ " ");
System.out.println();return;
}for (int i = 1; i <= N; i++) {if(isUsed[i])continue;
nums.push(i);
isUsed[i]= true;
DFS(index+ 1);
nums.pop();
isUsed[i]= false;
}
}public static voidmain(String[] args) {
N= 3;
DFS(0);//从第0层开始搜索
}
}
3.红黑树
4.hash表
4.1直接将关键字作为索引
packagech15;public classInfo {private intkey;privateString name;public Info(intkey, String name) {//TODO Auto-generated constructor stub
this.key =key;this.name =name;
}public intgetKey() {returnkey;
}public void setKey(intkey) {this.key =key;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}
}
packagech15;public classHashTable {privateInfo[] arr;publicHashTable() {//TODO Auto-generated constructor stub
arr = new Info[100];
}public HashTable(intmaxSize) {
arr= newInfo[maxSize];
}public voidinsert(Info info) {
arr[info.getKey()]=info;
}public Info find(intkey) {returnarr[key];
}
}
packagech15;public classTestHashTable {public static voidmain(String[] args) {
HashTable hTable= newHashTable();
hTable.insert(new Info(10, "张三"));
hTable.insert(new Info(15, "李四"));
System.out.println(hTable.find(15).getName());
}
}
4.2将单词转化为索引
packagech15;public classInfo {privateString key;privateString name;publicInfo(String key, String name) {//TODO Auto-generated constructor stub
this.key =key;this.name =name;
}publicString getKey() {returnkey;
}public voidsetKey(String key) {this.key =key;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}
}
packagech15;public classHashTable {privateInfo[] arr;publicHashTable() {//TODO Auto-generated constructor stub
arr = new Info[100];
}public HashTable(intmaxSize) {
arr= newInfo[maxSize];
}public voidinsert(Info info) {
arr[hashCode(info.getKey())]=info;
}publicInfo find(String key) {returnarr[hashCode(key)];
}public inthashCode(String key) {int hashValue = 0;for (int i = key.length() - 1; i >= 0; i--) {int letter = key.charAt(i) - 96;
hashValue+=letter;
}returnhashValue;
}
}
packagech15;public classTestHashTable {public static voidmain(String[] args) {
HashTable hTable= newHashTable();
hTable.insert(new Info("zhangsan", "张三"));
hTable.insert(new Info("lisi", "李四"));
System.out.println(hTable.find("zhangsan").getName());
}
}
以上方法也会存在一定的问题,当hashcode相同的时候。
packagech15;public classTestHashTable {public static voidmain(String[] args) {
HashTable hTable= newHashTable();
hTable.insert(new Info("abc", "张三"));
hTable.insert(new Info("bca", "李四"));
System.out.println(hTable.find("abc").getName());
System.out.println(hTable.find("bca").getName());
}
}
我们用幂函数的方式去重写hashcode
public inthashCode(String key) {int hashValue = 0;int pow27 = 1;for (int i = key.length() - 1; i >= 0; i--) {int letter = key.charAt(i) - 96;
hashValue+= letter *pow27;
pow27*= 27;
}returnhashValue;
}
packagech15;public classTestHashTable {public static voidmain(String[] args) {
HashTable hTable= newHashTable();
hTable.insert(new Info("abc", "张三"));
hTable.insert(new Info("bca", "李四"));
System.out.println(hTable.find("abc").getName());
System.out.println(hTable.find("bca").getName());
}
}
此时可以解决上面的问题,但是浪费太多内存了,因为字符串如果很长,数组容易越界或者内存溢出,因此需要进行取模运算。
public inthashCode(String key) {
BigInteger hashValue= new BigInteger("0");
BigInteger pow27= new BigInteger("1");for (int i = key.length() - 1; i >= 0; i--) {int letter = key.charAt(i) - 96;
BigInteger letterB= newBigInteger(String.valueOf(letter));
hashValue=hashValue.add(letterB.multiply(pow27));
pow27= pow27.multiply(new BigInteger(String.valueOf(27)));
}return hashValue.mod(newBigInteger(String.valueOf(key.length()))).intValue();
}