剑指offer-每日6题之第四天(java版)

原题链接:

 第一题:顺时针打印矩阵
 第二题:包含min函数的栈
 第三题:栈的压入、弹出序列
 第四题:从上往下打印二叉树
 第五题:二叉搜索树的后序遍历序列
 第六题:二叉树中和为某一值的路径

第一题:顺时针打印矩阵

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16 则依次打印出数字

1,2,3,4

8,12,16,15

14,13,9,5

6,7,11,10.

解析

从外到内,每次打印一圈的值(函数printOneCircle)

     打印一圈分为四部分:→,↓,←,↑,若把打印看成x,y轴,那么对四个部分要判断

      ①→  不用,因为横轴肯定大于start

      ②↓   start<endy

      ③←  start>endx&& start<endy

      ④↑    start<endx && start<endy-1  

      注意:当start*2的值超过矩阵的行和列数时,停止打印

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> list=new ArrayList<Integer>();
        int rows=matrix.length;
        int cols=matrix[0].length;
        if(matrix==null ||rows==0||cols==0)return null;
        int start=0;
        while(rows>start*2&&cols>start*2){
            printOneCircle(matrix,rows,cols,start,list);
            start++;    
        }
        return list;
    }
    public void printOneCircle(int [][]matrix,int rows,int cols,int start,ArrayList<Integer> list){
        int endx=cols-1-start;
        int endy=rows-1-start;
        for(int i=start;i<=endx;i++){
            list.add(matrix[start][i]);
        }
        if(start<endy){
            for(int i=start+1;i<=endy;i++)
                list.add(matrix[i][endx]);
      }
        if(start<endy && start<endx){
            for(int i=endx-1;i>=start;i--)
                list.add(matrix[endy][i]);
        }
        if(start<endy-1&& start<endx ){
            for(int i=endy-1;i>start;i--)
                list.add(matrix[i][start]);
        }
    }
}

第二题:包含min函数的栈

题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

解析

注意:时间复杂度o(1)

定义两个栈,一个数据栈s1,一个辅助栈help

s1栈放原本的数据,help栈放当前栈中最小的元素 

eg:    s1        2 1 2 6 0 5

         help     2 1 1 1 0 0     

import java.util.Stack;
public class Solution {
	Stack<Integer> s=new Stack<Integer>();
	Stack<Integer> help=new Stack<Integer>();
    public void push(int node) {
        s.push(node);
        if(help.isEmpty())
            help.push(node);
        else{
        	if(node<=help.peek())
        		help.push(node);
        	else help.push(help.peek());	
        }
    }   
    public void pop() {
        s.pop();
        help.pop();
    }
    public int top() {
    	 s.pop();
	return	help.pop();
        
    }
    public int min() {
  
    	return	help.peek();
        
    }
}

第三题:栈的压入、弹出序列

题目描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

解析

两重循环:

       外层循环控制出栈,出栈的条件是出栈序列没有遍历完

       内层循环控制入栈,入栈的条件是栈为空或者栈顶元素不等于当前的出栈顺序(当入栈的元素遍历完,直接返回false)

import java.util.Stack;
public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        if(pushA==null||popA==null||pushA.length!=pushA.length||pushA.length==0||popA.length==0)
            return false;
        Stack<Integer> stack=new Stack<Integer> ();
        int i=0;
        int j=0;
        while(j<popA.length){
            while(stack.isEmpty()||stack.peek()!=popA[j]){
                if(i==popA.length)return false;
                stack.push(pushA[i++]);
            }
            stack.pop();
            j++;
        }
        return true;
    }
   
}

第四题:从上往下打印二叉树

题目描述

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

解析

广度优先遍历:

      用队列实现,初始把根节点加到队列

      每次弹出根节点,再添加左子节点,最后添加右子节点,直到队列为空,停止

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        Queue<TreeNode> q=new LinkedList<TreeNode>();
        ArrayList<Integer> res=new ArrayList<Integer>();
        if(root==null){
            return res;
        }
        q.offer(root);
        while(!q.isEmpty()){
            TreeNode tree=q.poll();
            res.add(tree.val);
            if(tree.left!=null)
             q.offer(tree.left);
            if(tree.right!=null)
             q.offer(tree.right);
        }
        return res;
    }
}

第五题:二叉搜索树的后序遍历序列

题目描述

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

解析

递归( 分两个函数递归):

     首先要知道二叉搜索树的特征:

          eg:         7

                       /   \

                     3     10

                   /   \     /   \

                  1    4  8  12

     后续遍历结果为:1,4,3,8,12,10,7

由后续结果,可以看出,root在结果的最后一位,它的左子数是比它小的数,为1,4,3;它的右子数是比它大的数,为8,12,10;

要想判断是不是后续遍历,就要先找到根节点,然后找到左子树的位置,在判断右子树中是不是都是比root大的数

     如果当前root判断完了,还要递归的去判断左子树,右子树是否是二叉搜索树

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence.length == 0) return false;
    return VerifySquenceOfBST( sequence, 0,sequence.length-1);
    }
    public boolean VerifySquenceOfBST(int [] sequence,int start,int end) {

        if(start>=end)return true;
        //start==end对应的是叶子结点,start>end对应的是空树,这两种情况都是true
        //比如1 4 3 5这个二叉搜索树的后序遍历,没有右子树,在第二个递归中i=3,end-1=2,i>end-1
        int root=sequence[end];
        int i=start;
        for(;i<end;i++){
            if(sequence[i]>sequence[end])break;
        }//得到比根小的下标
        for(int j=i;j<end;j++){
            if(sequence[j]<sequence[end])
                return false;
        }

        return VerifySquenceOfBST( sequence, start,i-1)&& VerifySquenceOfBST( sequence, i,end-1);
    }
}

第六题:二叉树中和为某一值的路径

题目描述

输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

解析

递归,回溯:

   eg:   10

            / \

          5   12

          / \

         4  7

     要求路径和为22的

从root开始遍历,每次记录当前的路径和,如果路径和等于给定的数,且到达数的叶子节点,就得到一条路径

否则,继续遍历左子树,右子树

在遍历其他路径的时候,先要删除当前的节点

public class Solution {
    ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
    ArrayList<Integer> path=new ArrayList<Integer>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        if(root==null && target==0)return res;
        FindPath( root,target,0);
        return res;
    }
    public void FindPath(TreeNode root,int target,int curSum) {
        path.add(root.val);
        curSum+=root.val;
        if(curSum==target && root.left==null && root.right==null)
            res.add(new ArrayList<Integer>(path));
        if(root.left!=null)
            FindPath( root.left,target,curSum);
        if(root.right!=null)
            FindPath( root.right,target,curSum);
        path.remove(path.size()-1);
    }
}

猜你喜欢

转载自blog.csdn.net/ccccc1997/article/details/81209238