剑指Offer 31-32

112 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

31、栈的压入和弹出序列

题目:给定两个整数序列,第一个序列表示栈的压入顺序,要求判断第二个序列是否是第一个栈的弹出顺序。已知栈中所有元素都不同。

解题思路

本题实际上很简单,既然给了入栈顺序和出栈顺序,那么根据这两个序列进行模拟一下入栈和出栈的顺序即可,即:

  1. 初始化标记索引,标记索引指向序列二的第一个元素,之后根据序列一先入栈。
  2. 判断栈顶元素是否为序列二的标记索引的值,如果是则出栈,否则入栈。
  3. 循环第二步,直到栈空或栈顶元素和序列二标记索引元素不相等。
  4. 循环步骤1、2、3。
  5. 如果满足最终的栈为空,则序列二必定是满足第一个栈的出栈顺序。

根据此逻辑可得代码:

public boolean validateStackSequences(int[] pushed, int[] popped) {
    int cur = 0;
    Stack<Integer> stack = new Stack<>();
    for(int i=0;i<pushed.length;i++){
        stack.push(pushed[i]);
        while(!stack.isEmpty()&&popped[cur] == stack.peek()){
            cur++;
            stack.pop();
        }
    }

    return stack.isEmpty()&&cur==popped.length;
}

32、从上向下打印二叉树

题目:给定一颗二叉树,要求从上到下打印二叉树的每个节点,同一层中的节点按照从左向右的顺序打印。

解题思路

本题实际上就是二叉树的层序遍历,使用队列即可完成本题,每次遍历到一个节点的时候,都将节点的左右孩子放入队列,可得如下代码:

public int[] levelOrder(TreeNode root) {
    ArrayList<Integer> res = new ArrayList<>();
    if(root == null) return new int[0];
    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);
    while(!queue.isEmpty()){
        TreeNode node = queue.poll();
        res.add(node.val);
        if(node.left!=null) queue.offer(node.left);
        if(node.right!=null) queue.offer(node.right);
    }

    return res.stream().mapToInt(Integer::valueOf).toArray();
}

上述在将ArrayList转为数组的时候使用了Java8的新特性Stream。实际上此操作十分耗时,不如循环复制来的快,可采用如下方式循环赋值得到最终结果:

int[] result = new int[res.size()];
for(int i=0;i<res.size();i++){
    result[i] = res.get(i);
}
return result;