請實現一個函數,用來判斷一顆二叉樹是否是對稱的。注意,若是一個二叉樹同此二叉樹的鏡像是一樣的,定義其爲對稱的。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; } }