第二十一题:栈的压入、弹出序列
题目描述:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
思路:
首先判断第二个序列中的数字是否在栈顶,如果正好就是,那就把栈顶的数字pop出来,然后第二个序列继续推进;如果不是,则继续把第一个序列中的数字压入栈中。循环的结束标志是第二个序列为空,此时如果栈也正好为空,则返回true,否则返回false。
代码:
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> data = new Stack<>();
boolean ret = false;
if (pushA != null && popA != null &&
pushA.length == popA.length) {
int index_pop = 0;
int index_push = 0;
while (index_pop != popA.length) {
if (!data.isEmpty() &&
data.peek() == popA[index_pop]) {
data.pop();
index_pop++;
}else {
if (index_push == pushA.length) {
break;
}else {
data.push(pushA[index_push]);
index_push++;
}
}
}
if (data.isEmpty() && index_pop == popA.length) {
ret = true;
}
}
return ret;
}
}
第二十二题:从上往下打印二叉树
题目描述:
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
思路:
在纸上画一下整个一个过程就可以发现对于每一个结点的打印顺序可以用一个队列来控制先后,把根结点的左右子结点放入队列中,先进先出,左结点的左右结点又会放到队列的尾端。依此类推就可以实现一层一层地打印二叉树了。
代码:
import java.util.ArrayList;
import java.util.LinkedList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> ret = new ArrayList<>();
if (root != null) {
LinkedList<TreeNode> queue = new LinkedList<>();
queue.addLast(root);
while (!queue.isEmpty()) {
TreeNode tmp = queue.removeFirst();
ret.add(tmp.val);
if (tmp.left != null) {
queue.addLast(tmp.left);
}
if (tmp.right != null) {
queue.addLast(tmp.right);
}
}
}
return ret;
}
}
第二十三题:二叉搜索树的后序遍历序列
题目描述:
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
思路:
首先需要了解二叉搜索树的特点,就是左子树的数字小于根结点的数字,右子树的数字都大于根结点的数字。基于这个特点再结合二叉树的后序遍历,可以发现这个遍历序列的最后一个数字是整棵树的根结点,并且序列的前半段比根结点小的是左子树,比根结点大的是右子树。并且递归这个过程就可以判断该序列是不是二叉搜索树的后续遍历序列。
代码:
import java.util.Arrays;
public class Solution {
public boolean VerifySquenceOfBST(int [] sequence) {
boolean ret = false;
if (sequence != null && sequence.length > 0) {
ret = verify(sequence, 0, sequence.length - 1);
}
return ret;
}
public boolean verify(int [] sequence, int start, int end) {
int root = sequence[end];
int index = start;
if (start == end) {
return true;
}
for (int i=start; i < end; i++) {
if(sequence[i] > root) {
break;
}
index = i;
}
for (int i=index+1; i < end; i++) {
if (sequence[i] < root) {
return false;
}
}
boolean ret = true;
if (index >= start) {
ret = verify(sequence, start, index);
}
if (end > index+1) {
ret = ret && verify(sequence, index+1, end-1);
}
return ret;
}
}
第二十四题:二叉树中和为某一值的路径
题目描述:
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
思路:
其实很简单,因为要把跟节点到叶子结点所经过的路径的值加起来来比较是否符合要求,所以只要用前序遍历的方式就不会落下任何一条路径。并且在每条路径的访问过程中有一个sum值做和的记录,一旦访问到了叶子结点就比较和是否为target;不为叶子结点就继续递归访问。需要注意的是,不管是不是叶子结点,当前结点的访问之后要从访问路径中删去,以防止对其后访问造成影响。
代码:
import java.util.ArrayList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
if (root != null) {
ArrayList<Integer> tmp = new ArrayList<>();
find(root, target, tmp, 0);
}
return ret;
}
public void find(TreeNode root, int target, ArrayList<Integer> tmp, int sum) {
sum += root.val;
tmp.add(root.val);
if (root.left == null && root.right == null) {// 为叶子结点
if (sum == target) {
ret.add(new ArrayList<>(tmp));
}
} else {// 不为叶子结点
if (root.left != null) {
find(root.left, target, tmp, sum);
}
if (root.right != null) {
find(root.right, target, tmp, sum);
}
}
tmp.remove(tmp.size() - 1);
}
}