zoukankan      html  css  js  c++  java
  • 算法

    使用数组模拟栈和队列

    使用数组模拟栈,包括栈的 push、pop 和 peek 操作。

    public class ArrayStack {
        private Integer[] arr;
        private Integer size;
    
        public ArrayStack(int initSize) {
            if (initSize < 0) {
                throw new IllegalArgumentException("栈的大小不能小于 0");
            }
            arr = new Integer[initSize];
            size = 0;
        }
    
        public Integer peek() {
            if (size == 0) {
                return null;
            }
            return arr[size - 1];
        }
    
        public void push(Integer number) {
            if (size == arr.length) {
                throw new ArrayIndexOutOfBoundsException("栈已满!");
            }
            arr[size++] = number;
        }
    
        public Integer pop() {
            if (size == 0) {
                throw new ArrayIndexOutOfBoundsException("栈已空!");
            }
            return arr[--size];
        }
    }
    

    使用数组模拟队列,包括队列的 offer、poll 和 peek 操作。

    public class ArrayQueue {
        private Integer[] arr;
        private Integer size;
        private Integer first;
        private Integer last;
    
        public ArrayQueue(int initSize) {
            if (initSize < 0) {
                throw new IllegalArgumentException("队列长度不能小于 0!");
            }
            arr = new Integer[initSize];
            size = 0;
            //first 指向队首的位置
            first = 0;
            //last 指向队尾后空的位置
            last = 0;
        }
    
        public void offer(int number) {
            if (size == arr.length) {
                throw new ArrayIndexOutOfBoundsException("队列已满!");
            }
            arr[last++] = number;
            last = last < arr.length ? last : 0;
            size++;
        }
    
        public Integer poll() {
            if (size == 0) {
                throw new ArrayIndexOutOfBoundsException("队列已空!");
            }
            int res =  arr[first++];
            first = first < arr.length ? first : 0;
            size--;
            return res;
        }
    
        public Integer peek() {
            if (size == 0) {
                return null;
            }
            return arr[first];
        }
    }
    

    设计 getMin() 操作时间复杂度为 O(1) 的栈

    设计一个栈,获取栈内最小值操作为 O(1),兼具栈的 push、pop 功能。

    public class MyStack {
        private Stack<Integer> stackData;
        private Stack<Integer> stackMin;
    
        public MyStack() {
            this.stackData = new Stack<>();
            this.stackMin = new Stack<>();
        }
    
        public void push(int number) {
            if (this.stackMin.isEmpty()) {
                this.stackMin.push(number);
            } else {
                int temp = this.stackMin.peek();
                if (temp < number) {
                    this.stackMin.push(temp);
                } else {
                    this.stackMin.push(number);
                }
            }
            this.stackData.push(number);
        }
    
        public Integer pop() {
            if (this.stackData.isEmpty()) {
                throw new RuntimeException("栈已空!");
            }
            this.stackMin.pop();
            return this.stackData.pop();
        }
    
        public Integer getMin() {
            if (this.stackData.isEmpty()) {
                throw new RuntimeException("栈已空!");
            }
            return this.stackMin.peek();
        }
    }
    

    使用栈实现队列

    stack1 专门用来添加数据 offer(),stack2 专门用来查看和弹出数据 peek() poll()。

    addStack2() 有两个前提:

    • stack1 非空
    • stack1 需要将所有数据转移到 stack2
    public class StackToQueue {
        private Stack<Integer> stack1;
        private Stack<Integer> stack2;
    
        public StackToQueue() {
            this.stack1 = new Stack<>();
            this.stack2 = new Stack<>();
        }
    
        public void offer(int number) {
            this.stack1.push(number);
            addStack2();
        }
    
        public Integer peek() {
            if (this.stack2.isEmpty()) {
                return null;
            }
            return this.stack2.peek();
        }
    
        private void addStack2() {
            while (!this.stack1.isEmpty()) {
                this.stack2.push(this.stack1.pop());
            }
        }
    
        public Integer poll() {
            if (this.stack2.isEmpty()) {
                throw new RuntimeException("队列已空!");
            }
            return this.stack2.pop();
        }
    }
    

    使用队列实现栈

    使用两个队列,一个是存储队列,一个是 help 队列。

    helper()

    • 将 queue 队列的数据转移到 help 队列中,只留下 queue 队列尾部的一个元素作为返回值

    swap()

    • 将 queue 队列和 help 队列的引用互换
    public class QueueToStack {
        private Queue<Integer> queue;
        private Queue<Integer> help;
    
        public QueueToStack() {
            this.queue = new LinkedList<>();
            this.help = new LinkedList<>();
        }
    
        public void push(int number) {
            queue.offer(number);
        }
    
        public Integer peek() {
            if (queue.isEmpty()) {
                return null;
            }
            int res = helper();
            help.offer(res);
            swap();
            return res;
        }
    
        //将数据从 queue 转移到 help 中,留下一个数
        private Integer helper() {
            while (queue.size() > 1) {
                help.offer(queue.poll());
            }
            return queue.poll();
        }
    
        private void swap() {
            Queue<Integer> temp = queue;
            queue = help;
            help = temp;
        }
    
        public Integer pop() {
            if (queue.isEmpty()) {
                throw new RuntimeException("栈已空");
            }
            int res = helper();
            swap();
            return res;
        }
    }
    

    猫狗队列问题

    经典的问题,不赘述。思路是先将 Pet 这个类包装一下,打上时间戳,增加了一个变量 count。

    class PetEntry {
        private Pet pet;
        private long count;
    
        public PetEntry(Pet pet, long count) {
            this.pet = pet;
            this.count = count;
        }
    
        public Pet getPet() {
            return this.pet;
        }
    
        public long getCount() {
            return this.count;
        }
    
        public String getEntryPetType() {
            return this.pet.getPetType();
        }
    }
    

    然后将获得的一个个 PetEntry 对象添加到队列中,在添加的时候就会对 PetEntry 对象的类型做判断,如果是 Cat 类就进入 catQ,如果是 Dog 类就进入 dogQ。

    public class DogCatQueue {
        private Queue<PetEntry> dogQ;
        private Queue<PetEntry> catQ;
        private long count;
    
        public DogCatQueue() {
            this.dogQ = new LinkedList<>();
            this.catQ = new LinkedList<>();
            this.count = 0;
        }
    
        public void add(Pet pet) {
            if (pet.getPetType().equals("dog")) {
                this.dogQ.offer(new PetEntry(pet, this.count++));
            } else if (pet.getPetType().equals("cat")) {
                this.catQ.offer(new PetEntry(pet, this.count++));
            } else {
                throw new RuntimeException("宠物需为猫或狗");
            }
        }
    
        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.catQ.poll().getPet();
            } else if (this.catQ.isEmpty()) {
                return this.dogQ.poll().getPet();
            } else {
                throw new RuntimeException("队列已空!");
            }
        }
    
        public Dog pollDog() {
            if (this.dogQ.isEmpty()) {
                throw new RuntimeException("狗队列为空!");
            }
            return (Dog) this.dogQ.poll().getPet();
        }
    
        public Cat pollCat() {
            if (this.catQ.isEmpty()) {
                throw new RuntimeException("猫队列为空!");
            }
            return (Cat) this.catQ.poll().getPet();
        }
    
        public boolean isEmpty() {
            return this.dogQ.isEmpty() && this.catQ.isEmpty();
        }
    
        public boolean isDogQueueEmpty() {
            return this.dogQ.isEmpty();
        }
    
        public boolean isCatQueueEmpty() {
            return this.catQ.isEmpty();
        }
    }
    

    严格来说这不是一个算法题目,而是一个工程类题目,使用了装饰者设计模式,对原有的类进行包装,成为一个 Entry 类。

  • 相关阅读:
    网络流,再出发!
    2SAT
    并查集
    最大密度子图
    网络流提高专题(洛谷题单)
    JQuery 操作 ListBox间移动和ListBox内移动
    关于多表Update和Delete的应用
    XML格式与DataTable、DataSet、DataView格式的转换
    FCKeditor配置和精简
    点击fileupload后button事件不起作用
  • 原文地址:https://www.cnblogs.com/chenxianbin/p/11918965.html
Copyright © 2011-2022 走看看