• 算法初级面试题03——队列实现栈、栈实现队列、转圈打印矩阵、旋转矩阵、反转链表、之字打印矩阵、排序矩阵中找数


    第一部分主要讨论:栈、队列、数组矩阵相关的面试题

     

    题目一

    用数组结构实现大小固定的队列和栈

        public static class ArrayStack {
            private Integer[] arr;
            private Integer size;
    
            public ArrayStack(int initSize) {
                if (initSize < 0) {
                    throw new IllegalArgumentException("The init size is less than 0");
                }
                arr = new Integer[initSize];
                size = 0;
            }
    
            public Integer peek() {
                if (size == 0) {
                    return null;
                }
                return arr[size - 1];
            }
    
            public void push(int obj) {
                if (size == arr.length) {
                    throw new ArrayIndexOutOfBoundsException("The queue is full");
                }
                arr[size++] = obj;
            }
    
            public Integer pop() {
                if (size == 0) {
                    throw new ArrayIndexOutOfBoundsException("The queue is empty");
                }
                return arr[--size];
            }
        }
    
        public static class ArrayQueue {
            private Integer[] arr;
            private Integer size;
            private Integer first;
            private Integer last;
    
            public ArrayQueue(int initSize) {
                if (initSize < 0) {
                    throw new IllegalArgumentException("The init size is less than 0");
                }
                arr = new Integer[initSize];
                size = 0;
                first = 0;
                last = 0;
            }
    
            public Integer peek() {
                if (size == 0) {
                    return null;
                }
                return arr[first];
            }
    
            public void push(int obj) {
                if (size == arr.length) {
                    throw new ArrayIndexOutOfBoundsException("The queue is full");
                }
                size++;
                arr[last] = obj;
                last = last == arr.length - 1 ? 0 : last + 1;
            }
    
            public Integer poll() {
                if (size == 0) {
                    throw new ArrayIndexOutOfBoundsException("The queue is empty");
                }
                size--;
                int tmp = first;
                first = first == arr.length - 1 ? 0 : first + 1;
                return arr[tmp];
            }
        }
    实现代码

    题目二

    实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。

     【要求】

     1.pop、push、getMin操作的时间复杂度都是O(1)。

     2.设计的栈类型可以使用现成的栈结构。

    思路:利用两个栈来实现

    public class Code_02_GetMinStack {
        public static class MyStack1 {
            private Stack<Integer> stackData;
            private Stack<Integer> stackMin;
    
            public MyStack1() {
                this.stackData = new Stack<Integer>();
                this.stackMin = new Stack<Integer>();
            }
    
            public void push(int newNum) {
                if (this.stackMin.isEmpty()) {
                    this.stackMin.push(newNum);
                } else if (newNum <= this.getmin()) {
                    this.stackMin.push(newNum);
                }
                this.stackData.push(newNum);
            }
    
            public int pop() {
                if (this.stackData.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                int value = this.stackData.pop();
                if (value == this.getmin()) {
                    this.stackMin.pop();
                }
                return value;
            }
    
            public int getmin() {
                if (this.stackMin.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                return this.stackMin.peek();
            }
        }
    
        public static class MyStack2 {
            private Stack<Integer> stackData;
            private Stack<Integer> stackMin;
    
            public MyStack2() {
                this.stackData = new Stack<Integer>();
                this.stackMin = new Stack<Integer>();
            }
    
            public void push(int newNum) {
                if (this.stackMin.isEmpty()) {
                    this.stackMin.push(newNum);
                } else if (newNum < this.getmin()) {
                    this.stackMin.push(newNum);
                } else {
                    int newMin = this.stackMin.peek();
                    this.stackMin.push(newMin);
                }
                this.stackData.push(newNum);
            }
    
            public int pop() {
                if (this.stackData.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                this.stackMin.pop();
                return this.stackData.pop();
            }
    
            public int getmin() {
                if (this.stackMin.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                return this.stackMin.peek();
            }
        }
    
        public static void main(String[] args) {
            MyStack1 stack1 = new MyStack1();
            stack1.push(3);
            System.out.println(stack1.getmin());
            stack1.push(4);
            System.out.println(stack1.getmin());
            stack1.push(1);
            System.out.println(stack1.getmin());
            System.out.println(stack1.pop());
            System.out.println(stack1.getmin());
    
            System.out.println("=============");
    
            MyStack1 stack2 = new MyStack1();
            stack2.push(3);
            System.out.println(stack2.getmin());
            stack2.push(4);
            System.out.println(stack2.getmin());
            stack2.push(1);
            System.out.println(stack2.getmin());
            System.out.println(stack2.pop());
            System.out.println(stack2.getmin());
        }
    
    }
    实现代码

       

    题目三

    如何仅用队列结构实现栈结构?

    思路:两个队列复制到只剩下一个,留着最晚进入的然后给用户。

     

        public static class TwoStacksQueue {
            private Stack<Integer> stackPush;
            private Stack<Integer> stackPop;
    
            public TwoStacksQueue() {
                stackPush = new Stack<Integer>();
                stackPop = new Stack<Integer>();
            }
    
            public void push(int pushInt) {
                stackPush.push(pushInt);
            }
    
            public int poll() {
                if (stackPop.empty() && stackPush.empty()) {
                    throw new RuntimeException("Queue is empty!");
                } else if (stackPop.empty()) {
                    while (!stackPush.empty()) {
                        stackPop.push(stackPush.pop());
                    }
                }
                return stackPop.pop();
            }
    
            public int peek() {
                if (stackPop.empty() && stackPush.empty()) {
                    throw new RuntimeException("Queue is empty!");
                } else if (stackPop.empty()) {
                    while (!stackPush.empty()) {
                        stackPop.push(stackPush.pop());
                    }
                }
                return stackPop.peek();
            }
        }
    实现代码

     

    如何仅用栈结构实现队列结构?

    思路:①push要一次倒完 ②如果pop有东西一定不要倒

     

        public static class TwoQueuesStack {
            private Queue<Integer> queue;
            private Queue<Integer> help;
    
            public TwoQueuesStack() {
                queue = new LinkedList<Integer>();
                help = new LinkedList<Integer>();
            }
    
            public void push(int pushInt) {
                queue.add(pushInt);
            }
    
            public int peek() {
                if (queue.isEmpty()) {
                    throw new RuntimeException("Stack is empty!");
                }
                while (queue.size() != 1) {
                    help.add(queue.poll());
                }
                int res = queue.poll();
                help.add(res);
                swap();
                return res;
            }
    
            public int pop() {
                if (queue.isEmpty()) {
                    throw new RuntimeException("Stack is empty!");
                }
                while (queue.size() > 1) {
                    help.add(queue.poll());
                }
                int res = queue.poll();
                swap();
                return res;
            }
    
            private void swap() {
                Queue<Integer> tmp = help;
                help = queue;
                queue = tmp;
            }
    
        }
    实现代码

    题目四

     猫狗队列 【题目】 宠物、狗和猫的类如下:

    public class Pet {

      private String type; public Pet(String type) { this.type = type;

    }

    public String getPetType() { return this.type; } }

      

    public class Dog extends Pet { public Dog() { super("dog"); } }

    public class Cat extends Pet { public Cat() { super("cat"); } }

     

     

    实现一种狗猫队列的结构,要求如下:

    用户可以调用add方法将cat类或dog类的实例放入队列中;

    用户可以调用pollAll方法,将队列中所有的实例按照进队列的先后顺序依次弹出;

    用户可以调用pollDog方法,将队列中dog类的实例按照进队列的先后顺序依次弹出;

    用户可以调用pollCat方法,将队列中cat类的实例按照进队列的先后顺序依次弹出;

    用户可以调用isEmpty方法,检查队列中是否还有dog或cat的实例;

    用户可以调用isDogEmpty方法,检查队列中是否有dog类的实例;

    用户可以调用isCatEmpty方法,检查队列中是否有cat类的实例。

    思路很简单就加多一个时间戳count变量来区分,哪个先进入)

    public class Code_04_DogCatQueue {
    
        public static class Pet {
            private String type;
    
            public Pet(String type) {
                this.type = type;
            }
    
            public String getPetType() {
                return this.type;
            }
        }
    
        public static class Dog extends Pet {
            public Dog() {
                super("dog");
            }
        }
    
        public static class Cat extends Pet {
            public Cat() {
                super("cat");
            }
        }
    
        public static class PetEnterQueue {
            private Pet pet;
            private long count;
    
            public PetEnterQueue(Pet pet, long count) {
                this.pet = pet;
                this.count = count;
            }
    
            public Pet getPet() {
                return this.pet;
            }
    
            public long getCount() {
                return this.count;
            }
    
            public String getEnterPetType() {
                return this.pet.getPetType();
            }
        }
    
        public static class DogCatQueue {
            private Queue<PetEnterQueue> dogQ;
            private Queue<PetEnterQueue> catQ;
            private long count;
    
            public DogCatQueue() {
                this.dogQ = new LinkedList<PetEnterQueue>();
                this.catQ = new LinkedList<PetEnterQueue>();
                this.count = 0;
            }
    
            public void add(Pet pet) {
                if (pet.getPetType().equals("dog")) {
                    this.dogQ.add(new PetEnterQueue(pet, this.count++));
                } else if (pet.getPetType().equals("cat")) {
                    this.catQ.add(new PetEnterQueue(pet, this.count++));
                } else {
                    throw new RuntimeException("err, not dog or cat");
                }
            }
    
            public Pet pollAll() {
                if (!this.dogQ.isEmpty() && !this.catQ.isEmpty()) {
                    if (this.dogQ.peek().getCount() < this.catQ.peek().getCount()) {
                        return this.dogQ.poll().getPet();
                    } else {
                        return this.catQ.poll().getPet();
                    }
                } else if (!this.dogQ.isEmpty()) {
                    return this.dogQ.poll().getPet();
                } else if (!this.catQ.isEmpty()) {
                    return this.catQ.poll().getPet();
                } else {
                    throw new RuntimeException("err, queue is empty!");
                }
            }
    
            public Dog pollDog() {
                if (!this.isDogQueueEmpty()) {
                    return (Dog) this.dogQ.poll().getPet();
                } else {
                    throw new RuntimeException("Dog queue is empty!");
                }
            }
    
            public Cat pollCat() {
                if (!this.isCatQueueEmpty()) {
                    return (Cat) this.catQ.poll().getPet();
                } else
                    throw new RuntimeException("Cat queue is empty!");
            }
    
            public boolean isEmpty() {
                return this.dogQ.isEmpty() && this.catQ.isEmpty();
            }
    
            public boolean isDogQueueEmpty() {
                return this.dogQ.isEmpty();
            }
    
            public boolean isCatQueueEmpty() {
                return this.catQ.isEmpty();
            }
    
        }
    
        public static void main(String[] args) {
            DogCatQueue test = new DogCatQueue();
    
            Pet dog1 = new Dog();
            Pet cat1 = new Cat();
            Pet dog2 = new Dog();
            Pet cat2 = new Cat();
            Pet dog3 = new Dog();
            Pet cat3 = new Cat();
    
            test.add(dog1);
            test.add(cat1);
            test.add(dog2);
            test.add(cat2);
            test.add(dog3);
            test.add(cat3);
    
            test.add(dog1);
            test.add(cat1);
            test.add(dog2);
            test.add(cat2);
            test.add(dog3);
            test.add(cat3);
    
            test.add(dog1);
            test.add(cat1);
            test.add(dog2);
            test.add(cat2);
            test.add(dog3);
            test.add(cat3);
            while (!test.isDogQueueEmpty()) {
                System.out.println(test.pollDog().getPetType());
            }
            while (!test.isEmpty()) {
                System.out.println(test.pollAll().getPetType());
            }
        }
    
    }
    实现代码

    题目五

    锻炼宏观思路解题

    转圈打印矩阵

    【题目】 给定一个整型矩阵matrix,请按照转圈的方式打印它。


    打印结果为:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11, 10

    【要求】 额外空间复杂度为O(1)。

     思路:

        

    package class_03;
    
    public class Code_06_PrintMatrixSpiralOrder {
    
        public static void spiralOrderPrint(int[][] matrix) {
            //左上角
            int tR = 0;
            int tC = 0;
            //右下角
            int dR = matrix.length - 1;//行数
            int dC = matrix[0].length - 1;//列数
            while (tR <= dR && tC <= dC) {
                //左上角和右下角
                printEdge(matrix, tR++, tC++, dR--, dC--);
            }
        }
    
        public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
            if (tR == dR) {//行先相遇,打印目标是横的长方形
                for (int i = tC; i <= dC; i++) {
                    System.out.print(m[tR][i] + " ");
                }
            } else if (tC == dC) {//列先相遇,打印目标是竖的长方形
                for (int i = tR; i <= dR; i++) {
                    System.out.print(m[i][tC] + " ");
                }
            } else {
                int curC = tC;
                int curR = tR;
                //模拟转圈打印
                while (curC != dC) {
                    System.out.print(m[tR][curC] + " ");
                    curC++;
                }
                while (curR != dR) {
                    System.out.print(m[curR][dC] + " ");
                    curR++;
                }
                while (curC != tC) {
                    System.out.print(m[dR][curC] + " ");
                    curC--;
                }
                while (curR != tR) {
                    System.out.print(m[curR][tC] + " ");
                    curR--;
                }
            }
        }
    
        public static void main(String[] args) {
            int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
                    { 13, 14, 15, 16 } };
            spiralOrderPrint(matrix);
    
        }
    
    }
    实现代码

    题目六

    旋转正方形矩阵

    【题目】 给定一个整型正方形矩阵matrix,请把该矩阵调整成顺时针旋转90度的样子。

    【要求】 额外空间复杂度为O(1)。

     思路:

    package class_03;
    
    public class Code_05_RotateMatrix {
    
        public static void rotate(int[][] matrix) {
            int tR = 0;
            int tC = 0;
            int dR = matrix.length - 1;
            int dC = matrix[0].length - 1;
            while (tR < dR) {
                rotateEdge(matrix, tR++, tC++, dR--, dC--);
            }
        }
    
        public static void rotateEdge(int[][] m, int ax, int ay, int bx, int by) {
            int times = by - ay;
            int tmp = 0;
            for (int i = 0; i != times; i++) {
                tmp = m[ax][ay + i];
                m[ax][ay + i] = m[bx - i][ay];
                m[bx - i][ay] = m[bx][by - i];
                m[bx][by - i] = m[ax + i][by];
                m[ax + i][by] = tmp;
            }
        }
    
        public static void printMatrix(int[][] matrix) {
            for (int i = 0; i != matrix.length; i++) {
                for (int j = 0; j != matrix[0].length; j++) {
                    System.out.print(matrix[i][j] + " ");
                }
                System.out.println();
            }
        }
    
        public static void main(String[] args) {
            int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
                    { 13, 14, 15, 16 } };
            printMatrix(matrix);
            rotate(matrix);
            System.out.println("=========");
            printMatrix(matrix);
    
        }
    
    }
    实现代码

    题目七

    反转单向和双向链表

    【题目】 分别实现反转单向链表和反转双向链表的函数。

    【要求】 如果链表长度为N,时间复杂度要求为O(N),额外空间复杂度要求为O(1)

    package class_03;
    
    public class Code_07_ReverseList {
    
        public static class Node {
            public int value;
            public Node next;
            public Node(int data) {
                this.value = data;
            }
        }
    
        public static Node reverseList(Node head) {
            Node pre = null;
            Node next = null;
            while (head != null) {
                //把下一个节点先存起来
                next = head.next;
                //翻转节点指向
                head.next = pre;
                //把当前节点设置为下一个节点的前节点
                pre = head;
                //为下一次循环,推进一步
                head = next;
            }
            return pre;
        }
    
        public static class DoubleNode {
            public int value;
            public DoubleNode last;
            public DoubleNode next;
    
            public DoubleNode(int data) {
                this.value = data;
            }
        }
    
        public static DoubleNode reverseList(DoubleNode head) {
            DoubleNode pre = null;
            DoubleNode next = null;
            while (head != null) {
                next = head.next;
                head.next = pre;
                head.last = next;
                //把当前节点设置为下一个节点的前节点
                pre = head;
                //为下一循环做准备,往下一个要操作的节点移动
                head = next;
            }
            return pre;
        }
    
        public static void printLinkedList(Node head) {
            System.out.print("Linked List: ");
            while (head != null) {
                System.out.print(head.value + " ");
                head = head.next;
            }
            System.out.println();
        }
    
        public static void printDoubleLinkedList(DoubleNode head) {
            System.out.print("Double Linked List: ");
            DoubleNode end = null;
            while (head != null) {
                System.out.print(head.value + " ");
                end = head;
                head = head.next;
            }
            System.out.print("| ");
            while (end != null) {
                System.out.print(end.value + " ");
                end = end.last;
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            Node head1 = new Node(1);
            head1.next = new Node(2);
            head1.next.next = new Node(3);
            printLinkedList(head1);
            head1 = reverseList(head1);
            printLinkedList(head1);
    
            DoubleNode head2 = new DoubleNode(1);
            head2.next = new DoubleNode(2);
            head2.next.last = head2;
            head2.next.next = new DoubleNode(3);
            head2.next.next.last = head2.next;
            head2.next.next.next = new DoubleNode(4);
            head2.next.next.next.last = head2.next.next;
            printDoubleLinkedList(head2);
            printDoubleLinkedList(reverseList(head2));
    
        }
    
    }
    实现代码

    题目八

    “之”字形打印矩阵

    【题目】 给定一个矩阵matrix,按照“之”字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 “之”字形打印的结果为:1,2,5,9,6,3,4,7,10,11,8,12

    【要求】 额外空间复杂度为O(1)。

     思路:

    package class_03;
    
    public class Code_08_ZigZagPrintMatrix {
    
        public static void printMatrixZigZag(int[][] matrix) {
            int ax = 0;
            int ay = 0;
            int bx = 0;
            int by = 0;
            int endX = matrix.length - 1;
            int endY = matrix[0].length - 1;
            boolean fromUp = false;
            while (ax != endX + 1) {
                printLevel(matrix, ax, ay, bx, by, fromUp);
                ax = ay == endY ? ax + 1 : ax;
                ay = ay == endY ? ay : ay + 1;
                by = bx == endX ? by + 1 : by;
                bx = bx == endX ? bx : bx + 1;
                fromUp = !fromUp;
            }
            System.out.println();
        }
    
        public static void printLevel(int[][] m, int ax, int ay, int bx, int by,
                boolean f) {
            if (f) {
                while (ax != bx + 1) {
                    System.out.print(m[ax++][ay--] + " ");
                }
            } else {
                while (bx != ax - 1) {
                    System.out.print(m[bx--][by++] + " ");
                }
            }
        }
    
        public static void main(String[] args) {
            int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
            printMatrixZigZag(matrix);
    
        }
    
    }
    实现代码

    题目九

    在行列都排好序的矩阵中找数

    【题目】 给定一个有N*M的整型矩阵matrix和一个整数K,matrix的每一行和每一 列都是排好序的。实现一个函数,判断K是否在matrix中。

    例如: 0 1 2 5 2 3 4 7 4 4 4 8 5 7 7 9

    如果K为7,返回true;如果K为6,返回false。

    【要求】 时间复杂度为O(N+M),额外空间复杂度为O(1)。

     思路:

    package class_03;
    
    public class Code_09_FindNumInSortedMatrix {
    
        public static boolean isContains(int[][] matrix, int K) {
            int row = 0;
            int col = matrix[0].length - 1;
            while (row < matrix.length && col > -1) {
                if (matrix[row][col] == K) {
                    return true;
                } else if (matrix[row][col] > K) {
                    col--;
                } else {
                    row++;
                }
            }
            return false;
        }
    
        public static void main(String[] args) {
            int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0
                    { 10, 12, 13, 15, 16, 17, 18 },// 1
                    { 23, 24, 25, 26, 27, 28, 29 },// 2
                    { 44, 45, 46, 47, 48, 49, 50 },// 3
                    { 65, 66, 67, 68, 69, 70, 71 },// 4
                    { 96, 97, 98, 99, 100, 111, 122 },// 5
                    { 166, 176, 186, 187, 190, 195, 200 },// 6
                    { 233, 243, 321, 341, 356, 370, 380 } // 7
            };
            int K = 233;
            System.out.println(isContains(matrix, K));
        }
    
    }
    实现代码

     

     

  • 相关阅读:
    Weblogic任意文件上传漏洞(CVE-2018-2894)复现
    Angular动态创建组件之Portals
    nodejs 开发企业微信第三方应用入门教程
    系列文章|OKR与敏捷(三):赋予团队自主权
    Angular开发技巧
    系列文章|OKR与敏捷(二):实现全栈敏捷
    系列文章|OKR与敏捷(一):瀑布式目标与敏捷的冲突
    OKR与Scrum如何强强联手
    Service Worker
    RxJS 实现摩斯密码(Morse) 【内附脑图】
  • 原文地址:https://www.cnblogs.com/xieyupeng/p/10278930.html
Copyright © 2020-2023  润新知