请实现一个函数,用来判断一颗二叉树是否是对称的。注意,若是一个二叉树同此二叉树的镜像是一样的,定义其为对称的。java
/* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution { boolean isSymmetrical(TreeNode pRoot) { return isSymmetrical(pRoot,pRoot); } public boolean isSymmetrical(TreeNode n1,TreeNode n2){ if(n1 == null && n2 == null) return true; if(n1 == null || n2 == null) return false; if(n1.val != n2.val) return false; return isSymmetrical(n1.left,n2.right) && isSymmetrical(n1.right,n2.left); } }
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其余行以此类推。
解题思路:参见《剑指offer》p176,使用两个辅助栈进行操做node
import java.util.ArrayList; import java.util.Stack; public class Solution { public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) { ArrayList<ArrayList<Integer>> result = new ArrayList<>(); if(pRoot == null) return result; int layer = 1; Stack<TreeNode> odd = new Stack<>(); Stack<TreeNode> even = new Stack<>(); odd.push(pRoot); while(!odd.empty()||!even.empty()){ ArrayList<Integer> list = new ArrayList<>(); if((layer & 1) == 1){//位运算,判断是否为奇数;等价于layer%2 while(!odd.empty()){ TreeNode node = odd.pop(); list.add(node.val); if(node.left != null) even.push(node.left); if(node.right != null) even.push(node.right); } }else{ while(!even.empty()){ TreeNode node = even.pop(); list.add(node.val); if(node.right != null) odd.push(node.right); if(node.left != null) odd.push(node.left); } } result.add(list); layer++; } return result; } }
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
注意要使用isEmpty()数组
import java.util.ArrayList; import java.util.LinkedList; public class Solution { ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) { ArrayList<ArrayList<Integer>> result = new ArrayList<>(); if(pRoot == null) return result; LinkedList<TreeNode> queue = new LinkedList<>(); ArrayList<Integer> list = new ArrayList<>(); queue.offer(pRoot);//将根节点加入队列 int elementsCount = 1;//用于记录每一层的元素个数 while(!queue.isEmpty()){//注意LinkedList 是没有 enpty()方法的。 TreeNode node = queue.poll(); elementsCount--; list.add(node.val); if(node.left != null) queue.offer(node.left); if(node.right != null) queue.offer(node.right); if(elementsCount == 0){ result.add(list); list = new ArrayList<>(); elementsCount = queue.size(); } } return result; } }
请实现两个函数,分别用来序列化和反序列化二叉树app
/* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution { String Serialize(TreeNode root) { StringBuilder sb = new StringBuilder(); if(root == null) sb.append("$,"); else{ sb.append(root.val+","); sb.append(Serialize(root.left)); sb.append(Serialize(root.right)); } return sb.toString(); } int index = -1; TreeNode Deserialize(String str) { if(str == null || str == "") return null; String[] strArray = str.split(","); if(strArray.length == 0) return null; return DeserializeCore(strArray); } TreeNode DeserializeCore(String[] strArray){ TreeNode node = null; index++; if(!strArray[index].equals("$")){ node = new TreeNode(Integer.parseInt(strArray[index])); node.left = DeserializeCore(strArray); node.right = DeserializeCore(strArray); } return node; } }
给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / 3 7 / / 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。(换句话说,从小到大排列,第k个数字)ide
import java.util.ArrayList; public class Solution { ArrayList<TreeNode> list = new ArrayList<>(); TreeNode KthNode(TreeNode pRoot, int k) { if(k < 1 || pRoot == null) return null; LDR(pRoot); if(list.size() < k) return null; return list.get(k-1); } void LDR(TreeNode pRoot){ if(pRoot.left != null) LDR(pRoot.left); list.add(pRoot); if(pRoot.right!=null) LDR(pRoot.right); } }
如何获得一个数据流中的中位数?若是从数据流中读出奇数个数值,那么中位数就是全部数值排序以后位于中间的数值。若是从数据流中读出偶数个数值,那么中位数就是全部数值排序以后中间两个数的平均值。函数
题目解析:若是直接使用ArrayList每次进行排序再选取中位数的话,时间复杂度为O(n^2logn),每一次排序O(nlogn),共进行N次排序;而使用最大堆、最小堆操做,每次插入数据,取出数据均占用O(logn)的时间,因此总共占用时间复杂度为O(NlogN)ui
import java.util.PriorityQueue; import java.util.Comparator; public class Solution { PriorityQueue<Integer> minHeap = new PriorityQueue<>(); PriorityQueue<Integer> maxHeap = new PriorityQueue<>(new Comparator<Integer>(){ @Override public int compare(Integer i1,Integer i2){ return i2-i1; } }); public void Insert(Integer num) { minHeap.offer(num); if(minHeap.size()>maxHeap.size()){ maxHeap.offer(minHeap.poll()); }else{ maxHeap.offer(minHeap.poll()); minHeap.offer(maxHeap.poll()); } } public Double GetMedian() { if(minHeap.size()==0&&maxHeap.size()==0) return null; if(minHeap.size() == maxHeap.size()) return (double)(minHeap.peek()+maxHeap.peek())/2.0; return (double)maxHeap.peek(); } }
给定一个数组和滑动窗口的大小,找出全部滑动窗口里数值的最大值。例如,若是输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有如下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。this
import java.util.LinkedList; import java.util.ArrayList; public class Solution { public ArrayList<Integer> maxInWindows(int [] num, int size) { ArrayList<Integer> result = new ArrayList<>(); if(num.length<1||size<1||size>num.length) return result; LinkedList<Integer> deque = new LinkedList<>(); for(int i = 0;i<num.length;i++){ while(!deque.isEmpty() && num[deque.peekLast()] <= num[i]) deque.pollLast(); deque.offerLast(i); if(i>=size-1){ while(i-deque.peekFirst()>size-1) deque.pollFirst(); result.add(num[deque.peekFirst()]); } } return result; } }
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串全部字符的路径。路径能够从矩阵中的任意一个格子开始,每一步能够在矩阵中向左,向右,向上,向下移动一个格子。若是一条路径通过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,可是矩阵中不包含"abcb"路径,由于字符串的第一个字符b占据了矩阵中的第一行第二个格子以后,路径不能再次进入该格子。设计
public class Solution { public boolean hasPath(char[] matrix, int rows, int cols, char[] str) { if(matrix == null || rows<1 || cols<1 || str == null) return false; boolean[][] visited = new boolean[rows][cols]; int pathLength = 0; for(int row = 0;row<rows;row++) for(int col = 0 ;col<cols;col++){ if(hasPathCore(matrix,rows,cols,row,col,str,visited,pathLength)) return true; } return false; } public boolean hasPathCore(char[] matrix,int rows,int cols,int row,int col,char[] str,boolean[][] visited,int pathLength){ if(pathLength == str.length) return true; boolean hasPath = false; if(row>=0 && col>=0 && row<rows && col<cols && visited[row][col]==false && matrix[row*cols+col] == str[pathLength]){ pathLength++; visited[row][col] = true; hasPath = hasPathCore(matrix,rows,cols,row+1,col,str,visited,pathLength) ||hasPathCore(matrix,rows,cols,row-1,col,str,visited,pathLength) ||hasPathCore(matrix,rows,cols,row,col+1,str,visited,pathLength) ||hasPathCore(matrix,rows,cols,row,col-1,str,visited,pathLength); if(!hasPath){ pathLength--; visited[row][col] = false; } } return hasPath; } }
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,可是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人可以进入方格(35,37),由于3+5+3+7 = 18。可是,它不能进入方格(35,38),由于3+5+3+8 = 19。请问该机器人可以达到多少个格子?code
public class Solution { public int movingCount(int threshold, int rows, int cols) { if (threshold < 1 || rows < 1 || cols < 1) return 0; boolean[][] visited = new boolean[rows][cols]; return movingCountCore(threshold, 0, 0, rows, cols, visited); } public int movingCountCore(int threshold, int row, int col, int rows, int cols, boolean[][] visited) { int count = 0; if (check(threshold, row, col, rows, cols, visited)) { visited[row][col] = true; count = 1 + movingCountCore(threshold, row + 1, col, rows, cols, visited) + movingCountCore(threshold, row - 1, col, rows, cols, visited) + movingCountCore(threshold, row, col + 1, rows, cols, visited) + movingCountCore(threshold, row, col - 1, rows, cols, visited); } return count; } public boolean check(int threshold, int row, int col, int rows, int cols, boolean[][] visited) { if (row < 0 || col < 0 || row >= rows || col >= cols || visited[row][col]) return false; int num = 0; while (col != 0 || row != 0) { num += col % 10; num += row % 10; col /= 10; row /= 10; } if (num > threshold) return false; return true; } }