劍指offer 第十二天

58.對稱的二叉樹

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

59.==之字形打印二叉樹==

請實現一個函數按照之字形打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其餘行以此類推。
解題思路:參見《劍指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;
    } 
}

60.把二叉樹打印成多行

從上到下按層打印二叉樹,同一層結點從左至右輸出。每一層輸出一行。
注意要使用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;
    }
}

61.序列化二叉樹

請實現兩個函數,分別用來序列化和反序列化二叉樹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;
    }
}

62.二叉搜索樹的第K個結點

給定一顆二叉搜索樹,請找出其中的第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);
    }
}

63.數據流中的中位數

如何獲得一個數據流中的中位數?若是從數據流中讀出奇數個數值,那麼中位數就是全部數值排序以後位於中間的數值。若是從數據流中讀出偶數個數值,那麼中位數就是全部數值排序以後中間兩個數的平均值。函數

題目解析:若是直接使用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();
    }
}

64.互動窗口的最大值

給定一個數組和滑動窗口的大小,找出全部滑動窗口裏數值的最大值。例如,若是輸入數組{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;
    }
}

65.矩陣中的路徑

請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串全部字符的路徑。路徑能夠從矩陣中的任意一個格子開始,每一步能夠在矩陣中向左,向右,向上,向下移動一個格子。若是一條路徑通過了矩陣中的某一個格子,則該路徑不能再進入該格子。 例如 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;
    }
}

66.機器人的運動範圍

地上有一個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;
    }

}
相關文章
相關標籤/搜索