zoukankan      html  css  js  c++  java
  • 剑指offer 第十二天

    58.对称的二叉树

    请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

    /*
    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,使用两个辅助栈进行操作

    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.序列化二叉树

    请实现两个函数,分别用来序列化和反序列化二叉树

    /*
    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个数字)

    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)

    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]}。

    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。请问该机器人能够达到多少个格子?

    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;
        }
    
    }
    
  • 相关阅读:
    ios 开发证书制作
    iOS UILable 高度自适
    asp 中创建日志打印文件夹
    ios iphone、ipad启动画面尺寸
    ios 更改UITableview中Section的字体颜色
    Azure Blob 存储简介
    java追加文件
    java读取文件
    DNS原理及其解析过程
    单点登录原理与简单实现
  • 原文地址:https://www.cnblogs.com/guoyaohua/p/8625178.html
Copyright © 2011-2022 走看看