@LIUHUAN
2018-03-15T04:17:02.000000Z
字数 7788
阅读 1478
algorithm
n! = n*(n-1)*(n-2)...(1)
上面是阶乘的定义:
我们把问题抽象成一个函数,假设问题可以这么定义
那么通过变形,我们可以得到:
可以看出来,我们把一个大的问题求, 分解成一个小的问题求的,也可以理解,如果我知道的值,那么我就能够解决这个的问题了。
所有的递归问题,我们都可以假设我们已经有方法求出更小的问题直接定义出来,也就是说,我们在思考的过程当中是,先假设我们能够解决规模较小的问题,然后,再来思考更大的问题,我们该怎么解决。
(1).让我求f(n),->>>>(2).我就直接假设我已经能够有这个能力了f(n)定义出来 ->>>>(3).f(n) 什么时候能够直接得到问题的答案,也就是递归的出口 --->>>>> 这个就是递归调用函数的需要return的地方(4).组合一下更小规模情况下f(n-1)和f(n)的关系,阶乘函数是n*f(n-1)的关系 ->>>>
public static void main(String []args) {int n = 5;System.out.println("5! = " + factorial(n));}public static int factorial(int n) {/* (1).最为基本的情况,也就是说,这个问题已经不能再小了,我已经知道怎么解决了。所有的递归都需要有明确的返回,* (2).只有在最基本的情况下返回,递归才不会无线循环下去,因为递归是调用自己的。*/if (n <= 0 )return 1;else {/* (1).一个规模小的问题,和当前的问题的关系是什么* (2).这里阶乘的计算是 n*f(n-1)的关系* (3).如果是求和,那么是 n + f(n-1)的关系*/return n * factorial(n-1);}}
n*f(n-1) ->>>>> n + f(n-1)即可
class TreeNode {int v;TreeNode left,right;}public static void preOrder(TreeNode root) {if (root == null){ // 一颗空树,最基本的情况,什么时候不需要在递归了return ;}visited(root); // 1: 访问节点preOrder(root.left);//2 访问左子树节点preOrder(root.right);//3 访问右子树的节点}public static void visited(TreeNode node) {System.out.println(node.v);}
public class Solution{public static nodeCount = 0;public static void main(String[] args){TreeNode root = new TreeNode();preOrder(root);//从根节点开始遍历}public static void preOrder(TreeNode root) {if (root == null){ // 一颗空树,最基本的情况,什么时候不需要在递归了return ;}visited(root); // 1: 访问节点preOrder(root.left);//2 访问左子树节点preOrder(root.right);//3 访问右子树的节点}public static void visited(TreeNode node) {nodeCount++;// 统计节点的个数// 或者nodeCount += node.v + 1;//所有节点的值都+1,求和System.out.println(node.v);}}//end class Solution
public static void main(String[] args){Graph G = new Graph();DFS(G.get(0),G);// 表示从0 节点开始遍历}public static void BFS(Node S,Graph G) {/* 初始化数据结构* 队列Q* 是否遍历的标志hashmap*/Queue<Node> Q = new LinkedList<Node>();HashMap<Node,Boolean> visitedMap = new HashMap<Node,Boolean>();/** 初始化标志*/Q.add(S);visitedMap.put(S, true); // S 已经认为是在队列当中,说明已经要被访问了,所以这么标志while( !Q.isEmpty()) { // (0).队列非空Node q = Q.poll(); // (1).出队列visited(q); // (2).这个就是遍历函数,或者要通过遍历来实现的目标的函数,,也可以时其他的过程处理,bi'r比如计数,求和等/* (3).把它的相邻节点,有个求相邻节点的函数* 且未遍历到的标志为遍历并放入队列Q*/ArrayList<Node> adjNodeList = G.getAdjectList(q); // 获取相邻的节点for(int i = 0; i < adjNodeList.size() ; ++i) {/**没有被访问过,放到队列当中*/if (visitedMap.containsKey(adjNodeList.get(i)) == false) { // 没有被访问过Q.add(adjNodeList.get(i)); //加入到队列中visitedMap.put(adjNodeList.get(i),true);// 表示已经访问了}}//end for}// end while}public static void visited(Node s) {System.out.println(s); // 这里只是简单的打印一下,可进行性统计、计数等操作}
class TreeNode {int v;TreeNode left,right;/**(1).获取这个节点相邻节点,也就是从这个节点可以访问到的节点,左子树节点和右子树节点(2).虽然这个节点的父节点从实际画出来的结构看也能访问到(3).但是定义数据结构的时候,并没有看到有子节点访问父节点的路径(4).如果TreeNode 里面存储parent节点表示父节点,那么是可以访问到的,还要看数据结构怎么设计*/public ArrayList<TreeNode> getAdjectList(){ArrayList<TreeNode> adj = new ArrayList<TreeNode>();if(this.left != null ) {adj.add(this.left);}if(this.right != null ) {adj.add(this.right);}}}public static void BFS(TreeNode root) {/* 初始化数据结构* 队列Q* 是否遍历的标志hashmap*/Queue<Node> Q = new LinkedList<Node>();HashMap<Node,Boolean> visitedMap = new HashMap<Node,Boolean>();/** 初始化标志*/Q.add(root);visitedMap.put(root, true); // root 已经认为是在队列当中,说明已经要被访问了,所以这么标志while( !Q.isEmpty()) { // (0).队列非空TreeNode q = Q.poll(); // (1).出队列visited(q); // (2).这个就是遍历函数,或者要通过遍历来实现的目标的函数,,也可以时其他的过程处理,比如计数,求和等/* (3).把它的相邻节点,有个求相邻节点的函数* 且未遍历到的标志为遍历并放入队列Q*/ArrayList<TreeNode> adjNodeList = q.getAdjectList(); // 获取相邻的节点for(int i = 0; i < adjNodeList.size() ; ++i) {/**没有被访问过,放到队列当中*/if (visitedMap.containsKey(adjNodeList.get(i)) == false) { // 没有被访问过Q.add(adjNodeList.get(i)); //加入到队列中visitedMap.put(adjNodeList.get(i),true);// 表示已经访问了}}//end for}// end while}public static void visited(TreeNode s) {System.out.println(s); // 这里只是简单的打印一下,可进行性统计、计数等操作}
/**** A----B D E* | | | |* F----G H I* | |* J K L M* | |* N O----P----Q* (x-1,y-1)---(x-1,y)----(x,y-1)* (x , y-1)---(x , y)----(x,y+1)* (x+1,y-1)---(x+1,y)----(x+1,y+1)** 11110110101100000000answer:1** 11000110000010000011* answer:3*/public class Solution {public static HashMap<NodeValue,Boolean> visitedMap = new HashMap<NodeValue,Boolean>();public static void main(String[] args) {char [][] grid = new char[n][n];System.out.println(grid);}public static int numIslands(char[][] grid) {// 每一个节点都需要遍历,其实,已经遍历过的节点,会在visitedMap当中标志,不会添加相邻节点到队列当中int area = 0;int count = 0;for(int x =0; x < grid.length;++x) {for(int y = 0; y < grid[0].length;++y) {if(visitedMap.containsKey(new NodeValue(x,y)) == false) {BFS(grid,x,y);count ++;// 表示找到了一个连通分量/**if(area < tarea) {area = tarea;}**/}}}return count;}/*** grid 可以认为是一个图,startNodex,startNodey 表示开始遍历的节点* */public static int BFS(char[][] grid,int startx,int starty) {int area = 1; //当前只有一个节点Queue<NodeValue> Q = new LinkedList<NodeValue>();NodeValue e = new NodeValue(starty, starty);Q.add(e);visitedMap.put(e, true);while(! Q.isEmpty()) {NodeValue q = Q.poll();ArrayList<NodeValue> adjlist = getAdjList(grid,q);for(int i = 0 ;i < adjlist.size(); ++i) {if(visitedMap.containsKey(adjlist.get(i)) == false) {Q.add(adjlist.get(i));visitedMap.put(adjlist.get(i), true);area += 1;// 说明这个是可以到达的和startx,starty 是相邻的}}}return area;}/**寻找其相邻节点的函数*/public static ArrayList<NodeValue> getAdjList(char[][] grid,NodeValue e) {ArrayList<NodeValue> adjlist = new ArrayList<NodeValue>();int xlen = grid.length;int ylen = grid[0].length;if(e.x - 1 >=0 ) { // 上面if (grid[e.x -1 ][e.y] == '1') {adjlist.add(new NodeValue(e.x-1,e.y));}}if(e.y - 1 >=0 ) { //左面if (grid[e.x ][e.y - 1 ] == '1') {adjlist.add(new NodeValue(e.x,e.y - 1 ));}}if(e.x + 1 < xlen ) { // 下面if (grid[e.x + 1 ][e.y] == '1') {adjlist.add(new NodeValue(e.x + 1,e.y));}}if(e.y + 1 < ylen ) { // 右面if (grid[e.x ][e.y + 1] == '1') {adjlist.add(new NodeValue(e.x,e.y + 1));}}return adjlist;}}class NodeValue{public int x, y;public NodeValue(int x,int y){this.x = x;this.y = y;}@Overridepublic boolean equals(Object obj) {// TODO Auto-generated method stubif(this == obj)return true;if(obj == null)return false;NodeValue node = (NodeValue)obj;return this.x == node.x && this.y == node.y;}}
/**是否已经被遍历的标志,如果被遍历了,是不会在进行遍历的*/public static HashMap<Node,Boolean> visitedMap= new HashMap<Node,Boolean>();public static void main(String[] args) {Graph G = new Graph();Node start;/**//每个节点开始去遍历,按照一个图所有节点之间都是可以到达的化,这种做法是不必要的,因为从任何一个节点都是可以遍历整个图的,但是如果这个图中有两个不可达的节点,这个循环就是必要的了。*/for(int i = 0 ;i < G.size(); ++i)if (visitedMap.get(G.get(i)) == false)DFS(G.get(i),G);}public static void DFS(Node s,Graph G){if( visitedMap.get(s) == true){/**递归的出口一定要有,* 已经被遍历了,所有不需要再遍历了,那么直接返回吧*/return ;}/**没有被遍历、那么遍历一下、设置标志位*/visit(s);//遍历下visitedMap.put(s,true);// 标志位已经遍历了/** 获取相邻节点,并遍历*/ArrayList<Node> adjList = G.getAdjNodeList(s,G);for(int i = 0; i < adjList.size(); ++i){Node newNode = adjList.get(i);if (visitedMap.contains(newNode) == false) {DFS(newNode,G);//newNode 作为一个新的节点,从这里又开始向它的相邻节点遍历了}}}public static void visit(Node s) {System.out.println(s);// 只是打印}