剑指Offer-学习计划(六)模拟

剑指 Offer 29. 顺时针打印矩阵

剑指 Offer 31. 栈的压入、弹出序列

题目一:栈的压入、弹出序列

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

示例 1:

输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

示例 2:

输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。

解法一:以顺序双端队列为基础模拟栈的出入,首先遍历pushed,压入栈中;之后while一下,比较长度 非空 弹出和popped;之后弹出,最后比对长度是否一致

public boolean validateStackSequences(int[] pushed, int[] popped) {
        Deque<Integer> stack = new ArrayDeque<>();
        int j = 0;
        for (Integer elem : pushed) {
            stack.push(elem);
            while (j<popped.length && !stack.isEmpty() && stack.peek() == popped[j]){
                stack.pop();
                j++;
            }
        }
        return j==popped.length;
    }

 解法二:也可以引入双指针,直接在pushed上模拟栈来达到O(1)的空间复杂度

 public boolean validateStackSequences(int[] pushed, int[] popped) {
        int top = -1, toDiscover = 0;
        for(int e: popped) {
            if (top != -1 && pushed[top] == e) {
                top--;
                continue;
            }
            while(toDiscover < pushed.length && pushed[toDiscover] != e) {
                top++;
                pushed[top] = pushed[toDiscover];
                toDiscover++;
            }
            if(toDiscover == pushed.length) return false;
            toDiscover++;
        }
        return true;
    }

题目二:顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

 解法一:看注释就行了,他就是模拟了一个矩阵,看着复杂,如果逻辑对很快就能出来

public int[] spiralOrder(int[][] matrix) {
      if (matrix.length == 0) return new int[0];
        // 当前打印上下左右四个边界,也就是当前所在的行、列
        int m = matrix.length, n = matrix[0].length;
        int[] res = new int[m * n];
        int u = 0, d = matrix.length - 1, l = 0, r = matrix[0].length - 1;
        int idx = 0;
        while (true) {
            // 在左上角时,从左往右
            for (int i = l; i <= r; i++) {
                res[idx++] = matrix[u][i]; // 打印完本行,上边界向下移动一位
            }
            if (++u > d) { // 上下边界相遇了,说明遍历结束
                break;
            }
            // 在右上角时,从上往下
            for (int i = u; i <= d; i++) {
                res[idx++] = matrix[i][r]; // 打印完本列,右边界左移一位
            }
            if (--r < l) { // 左右边界相遇,说明遍历结束
                break;
            }
            // 在右下角时,从右向左
            for (int i = r; i >= l; i--) {
                res[idx++] = matrix[d][i];
            }// 打印完本行,下边界上移一位
            if (--d < u) {
                break; // 上下边界相遇,说明遍历结束
            }
            // 在左下角时,从下往上
            for (int i = d; i >= u; i--) {
                res[idx++] = matrix[i][l]; //打印完本列,左边界右移动一位
            }
            if (++l > r) { // 左右边界相遇,遍历结束
                break;
            }
        }
        return res;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值