java算法之剑指offer题目整理2-树图篇
树
1. 如果给出一个二叉排序树的后序遍历,可以还原这课二叉排序树,相当于原来是由中序遍历来分左右,现在是由二叉排序树的性质来分左右。原来是由中序序列来确定节点是在左边还是右边,现在则是直接将节点的值与根节点比较来确定节点的插入位置
int数组的划分,除了用数组、左序列、右序列,还可以用System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
采用队列,依据bfs,将链式存储结构的二叉树转变为顺序存储结构。之后用队列,将其还原。
public class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { if(root == null) return "[]"; StringBuffer res = new StringBuffer("["); // 使用StringBuffer是可以动态的添加元素 Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.offer(root); while(!queue.isEmpty()){ // bfs TreeNode tmp = queue.poll(); if(tmp != null){ res.append(tmp.val + ","); queue.offer(tmp.left); queue.offer(tmp.right); }else{ res.append("null,"); } } res.deleteCharAt(res.length()-1); //删除最后一个字符 res.append("]"); return res.toString(); // 将StringBuffer转化为String. // 结果为二叉树的层序遍历序列。该层序遍历与之前的依据层序遍历和中序遍历求解中的层序遍历的区别在于,这次的层序遍历有null的存在。 } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { // 借助队列复原 if(data.equals("[]")) return null; // 空树返回null即可 String res[] = data.substring(1, data.length()-1).split(","); // 先用substring截取字符串,再用split将其分割 TreeNode root = new TreeNode(Integer.valueOf(res[0]).intValue()); // String => Integer => int Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.offer(root); int i = 1, size = res.length; while(!queue.isEmpty()){ // 依据完全二叉树的的层序遍历逆向还原该完全二叉树 TreeNode top = queue.poll(); if(!res[i].equals("null")){ // 对当前节点的左孩子进行判断,如果该值不为空,就说明左孩子存在,则创建 top.left = new TreeNode(Integer.valueOf(res[i]).intValue()); // 先创建树根的左孩子,在将左孩子添加入队列中 queue.offer(top.left); // top.left为null,不在需要再次赋值 } i++; // i++必须放这里,如果放在上面的if中的话,当res[i]为null的时候,会导致始终无法指向res中的下一个元素 if(!res[i].equals("null")){ top.right = new TreeNode(Integer.valueOf(res[i]).intValue()); queue.offer(top.right); } i++; } return root; } // 如果一个节点为null,则不需要赋值为null,直接不赋值就可以了 } // ArrayList、LinkedList可以添加null变量 // 可以先添加null,然后再删除,直到碰到元素为止 // 这题的判题方法是将你复原的树与原来的树进行比较,如果相同,则为正确。不用在意序列化的结果。
图
/* 当搜索图中符合条件的路径的时候,dfs更优,bfs暂时没有想到好的解法。例如剑指offer中给出了一个含有字符的图,再给出一个字符串,求字符串是否出现在图中,这题bfs我暂时没有想到如何解。 */ class Solution { public boolean dfs(char[][] board, String word, int max_level, int level, int[][] vis, int a, int b){ if(board[a][b] == word.charAt(level)){ level = level + 1; vis[a][b] = 1; }else{ return false; } if(level == max_level){ return true; } int x[] = {0, 0, 1, -1}; int y[] = {1, -1, 0, 0}; int row = board.length; int col = board[0].length; for(int i = 0; i < 4; i++){ if(a+x[i] >= 0 && a+x[i] <row && b+y[i] >= 0 && b+y[i] < col && vis[a+x[i]][b+y[i]] == 0){ if(dfs(board, word, max_level, level, vis, a+x[i], b+y[i])){ return true; } } } vis[a][b] = 0; // 必须加,应为传入的vis数组的变化会对原来的数组产生影响 return false; } public boolean exist(char[][] board, String word) { int row = board.length; int col = board[0].length; int strlen = word.length(); for(int i = 0; i < row; i++){ for(int j = 0; j < col; j++){ int[][] vis = new int[row][col]; // 初始化是0 if(dfs(board, word, strlen, 0, vis, i, j)){ return true; } } } return false; } } // class Solution { // public class Node{ // int x, y, layer; // } // public boolean exist(char[][] board, String word) { // int row = board.length; // int col = board[0].length; // int strlen = word.length(); // int x[] = {0, 0, 1, -1}; // int y[] = {1, -1, 0, 0}; // for(int i = 0; i < row; i++){ // for(int j = 0; j < col; j++){ // if(word.charAt(0) == board[i][j]){ // int[][] vis = new int[row][col]; // 初始化是0 // Node root = new Node(); // root.x = i; // root.y = j; // root.layer = 0; // Queue<Node> q = new LinkedList<Node>(); // q.offer(root); // while(q.peek() != null){ // Node head = q.poll(); // if(word.charAt(head.layer) == board[head.x][head.y]){ // vis[head.x][head.y] = 1; // }else{ // continue; // } // if(head.layer == strlen - 1){ // return true; // } // if(head.layer > strlen - 1){ // continue; // } // for(int k = 0; k < 4; k++){ // if(head.x+x[k] >=0 && head.x+x[k] < row && head.y+y[k] >= 0 && head.y+y[k] < col && vis[head.x+x[k]][head.y+y[k]] == 0 ){ // // System.out.println(head.x+x[k]); // // System.out.println(head.y+y[k]); // if(word.charAt(head.layer+1) == board[head.x+x[k]][head.y+y[k]]){ // Node node = new Node(); // node.x = head.x+x[k]; // node.y = head.y+y[k]; // node.layer = head.layer + 1; // q.offer(node); // // System.out.println(board[node.x][node.y]); // } // } // } // // vis[head.x][head.y] = 0; // } // } // } // } // return false; // } // } /* java数组创建 // int [] a = new int [5]; //第一种:初始化数组没有赋值 数组长度为5 int型的数组里的值全为0 // int [] a = new int[]{10,20,30,40};//第二种:分配数组空间同时赋值。数组长度为4,数组下标从0开始 a[0],a[1],a[2],a[3] // int [] a = {10,20,30,40};//或者直接赋值 int[][] a = new int[2][3]; */