《剑指offer》算法题第六天

今日题目:

  1. 顺时针打印矩阵
  2. 包含min函数的栈
  3. 栈的压入、弹出序列
  4. 从上到下打印二叉树
  5. 二叉树搜索树的后序遍历序列
  6. 二叉树中和为某一值的路径

今天的题目都比较简单,下面一一介绍:

1. 顺时针打印矩阵

题目描述:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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.

思路:
运用类似于剥洋葱的方法将矩阵一层一层地输出。

代码如下:

 1 public class Solution {
 2     public ArrayList<Integer> printMatrix(int [][] matrix) {
 3         ArrayList<Integer> res = new ArrayList();
 4         if(matrix.length == 0) return res;
 5         int colBegin = 0, colEnd = matrix[0].length-1;
 6         int rowBegin = 0, rowEnd = matrix.length-1;
 7         while(colBegin <= colEnd && rowBegin <= rowEnd){
 8             for(int i = colBegin; i <= colEnd; i++)
 9                 res.add(matrix[rowBegin][i]);
10             rowBegin++;
11             
12             for(int i = rowBegin; i <= rowEnd; i++)
13                 res.add(matrix[i][colEnd]);
14             colEnd--;
15             
16             if(rowBegin <= rowEnd){
17                 for(int i = colEnd; i >= colBegin; i--)
18                 res.add(matrix[rowEnd][i]);
19                 rowEnd--;
20             }
21             if(colBegin <= colEnd){
22                 for(int i = rowEnd; i >= rowBegin; i--)
23                 res.add(matrix[i][colBegin]);
24                 colBegin++;
25             }
26         }
27         return res;
28     }
29 }

 

2. 包含min函数的栈

题目描述:
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

思路:
维护两个栈,一个用来存数据,一个用来存当前的最小值。

代码如下:

 1 public class Solution {
 2 
 3     Stack<Integer> stack = new Stack();
 4     Stack<Integer> min_stack = new Stack();
 5     public void push(int node) {
 6         stack.push(node);
 7         if(min_stack.empty())
 8             min_stack.push(node);
 9         else{
10             if(min_stack.peek() >= node)
11                 min_stack.push(node);
12         }
13     }
14     
15     public void pop() {
16         int num = stack.pop();
17         if(num == min_stack.peek())
18             min_stack.pop();
19     }
20     
21     public int top() {
22         return stack.peek();
23     }
24     
25     public int min() {
26         if(min_stack.empty())
27             return -1;
28         else
29             return min_stack.peek();
30     }
31 }

 

3.栈的压入、弹出序列

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

思路:
维护一个栈,同时遍历两个序列,如果两个序列一个位置的值不相同,则判断弹出序列和栈顶的值是否相同,若不同,将压入序列的当前值压入栈中;若相同,将栈顶弹出。

代码如下:

 1 import java.util.ArrayList;
 2 import java.util.Stack;
 3 public class Solution {
 4     public boolean IsPopOrder(int [] pushA,int [] popA) {
 5         Stack<Integer> stack = new Stack();
 6         int i = 0, j = 0;
 7         while(i < pushA.length){
 8             if(pushA[i] == popA[j]){
 9                 i++;
10                 j++;
11                 continue;
12             }else if(!stack.empty() && stack.peek() == popA[j]){
13                 stack.pop();
14                 j++;
15             }else{
16                 stack.push(pushA[i]);
17                 i++;
18             }
19         }
20         while(j < popA.length){
21             if(stack.empty() || stack.pop() != popA[j])
22                 return false;
23             j++;
24         }
25         return true;
26     }
27 }

 

4. 从上到下打印二叉树

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

思路:没什么好说的,队列实现层次遍历。

代码如下:

 1 public class Solution {
 2     public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
 3         ArrayList<Integer> res = new ArrayList();
 4         if(root == null) return res;
 5         LinkedList<TreeNode> queue = new LinkedList();
 6         queue.offer(root);
 7         while(!queue.isEmpty()){
 8             root = queue.poll();
 9             res.add(root.val);
10             if(root.left != null)
11                 queue.offer(root.left);
12             if(root.right != null)
13                 queue.offer(root.right);
14         }
15         return res;
16     }
17 }

 

 

5. 二叉搜索树的后序遍历序列

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

思路:
这题考察的是二叉搜索树的性质:左子树小于根,右子树大于跟
以及后序遍历序列的性质:最后一个数为根节点
清楚这两单就很容易写出代码

代码如下:

 1 public class Solution {
 2     public boolean VerifySquenceOfBST(int [] sequence) {
 3         if(sequence.length <= 1)
 4             return sequence.length==1;
 5         return isbst(sequence,0,sequence.length-1);
 6     }
 7     
 8     public boolean isbst(int[] nums,int start,int end){
 9         if(start > end) return true;
10         int root = nums[end];
11         int ind = start;
12         while(nums[ind] < root) ind++;
13         for(int i = ind; i < end; i++){
14             if(nums[i] < root)
15                 return false;
16         }
17         return isbst(nums,start,ind-1)&&isbst(nums,ind,end-1);
18     }
19 }

 

 

6.二叉树中和为某一值的路径

题目描述:
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

思路:
题目比较简单,利用DFS就能实现,但是得注意判断符合条件语句和回溯的细节

代码如下:

 1 public class Solution {
 2     ArrayList<ArrayList<Integer>> res = new ArrayList();
 3     public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
 4         if(root == null) return res;
 5         findpath(root,target,new ArrayList());
 6         return res;
 7     }
 8     public void findpath(TreeNode root,int target,ArrayList<Integer> tmp){
 9         tmp.add(root.val);
10         if(root.left == null && root.right==null){
11             if(target == root.val)
12                 res.add(new ArrayList(tmp));
13         }else{
14             if(root.left != null)
15             findpath(root.left,target-root.val,tmp);
16         if(root.right != null)
17             findpath(root.right,target-root.val,tmp);
18         }
19         tmp.remove(tmp.size()-1);
20     }
21 }

 

posted @ 2018-02-02 19:27  wezheng  阅读(200)  评论(0编辑  收藏  举报