算法之堆栈问题

堆栈

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

  1. 用数组结构实现队列结构

    public class ArrayQueue {
    
        private Integer [] arr;
        private int size;
        private int first;
        private int end;
    
        //初始化队列
        public void ArrayQueue(int initSize) {
            if (initSize < 0) {
                throw new IllegalArgumentException("The init size is less than 0");
            }
            arr = new Integer[initSize];
            size=0;
            first=0;
            end=0;
        }
    
        //进队
        public void push(int obj) {
            if (size == arr.length) {
                throw new ArrayIndexOutOfBoundsException("The queue is full");
            }
            size++;
            arr[end] = obj;
            end = end == arr.length-1 ? 0 : end + 1;
        }
    
        //取队头元素
        public int peek() {
            if (size == 0) {
                throw new ArrayIndexOutOfBoundsException("The queue is full");
            }
            return arr[first];
        }
    
        //出队
        public int pop() {
            if (size == 0) {
                throw new ArrayIndexOutOfBoundsException("The queue is full");
            }
            size--;
            int temp = arr[first];
            first = first == arr.length-1 ? 0 : first + 1;
            return temp;
        }
    
    
    }
    
    
  2. 用数组结构实现栈结构

    public class ArrayStack {
    
        private Integer [] arr;
        private int size;
    
        //初始化栈
        public void ArrayStack(int initSize) {
            if (initSize < 0) {
                throw new IllegalArgumentException("The init size is less than 0");
            }
            arr = new Integer[initSize];
            size = 0;
        }
    
        //进栈
        public void push(int num) {
            if (size == arr.length) {
                throw new ArrayIndexOutOfBoundsException("The stack is full");
            }
            arr[size++] = num;
        }
    
        //取栈顶元素
        public int peek() {
            if (size == 0) {
                throw new ArrayIndexOutOfBoundsException("The stack is empty");
            }
            return arr[size-1];
        }
    
        //出栈
        public int pop() {
            if (size == 0) {
                throw new ArrayIndexOutOfBoundsException("The stack is empty");
            }
            return arr[--size];
        }
    
    }
    
    

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

  1. 【要求】
  • pop、push、getMin操作的时间复杂度都是O(1)。
  • 设计的栈类型可以使用现成的栈结构。
  1. 思路
  • 准备两个栈,一个dataStack栈,一个minStack栈
  • 当dataStack栈中压入第一个数时,minStack栈同时也压入第一个数;
  • 之后当dataStack栈中每压入一个数时,将这个数和minStack栈的栈顶作比较,若当前数比minStack的栈顶小,则minStack栈压入当前数,否则将minStack的栈顶再压入一遍;
  • 当出栈时,dataStack栈和minStack栈同步出栈即可;
  1. 代码
    package day03;
    
    import java.util.Stack;
    
    public class GetMinStack {
    
        public class MyStack1 {
    
            private Stack<Integer> dataStack;
            private Stack<Integer> minStack;
    
    
            public void push(int newValue) {
                if (minStack.isEmpty()) {
                    minStack.push(newValue);
                } else if (getMin() > newValue) {
                    minStack.push(newValue);
                } else {
                    minStack.push(minStack.peek());
                }
                dataStack.push(newValue);
            }
    
    
            public int pop() {
                if (dataStack.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                minStack.pop();
                return dataStack.pop();
            }
    
    
            public int getMin() {
                if (minStack.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                return this.minStack.peek();
            }
        }
    
    
        public class MyStack2 {
    
            private Stack<Integer> dataStack;
            private Stack<Integer> minStack;
    
    
            public void push(int newValue) {
                if (minStack.isEmpty()) {
                    minStack.push(newValue);
                } else if (getMin() >= newValue) {
                    minStack.push(newValue);
                }
                dataStack.push(newValue);
            }
    
    
            public int pop() {
                if (dataStack.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                int value=dataStack.pop();
                if (value == getMin()) {
                    minStack.pop();
                }
                return value;
            }
    
    
            public int getMin() {
                if (minStack.isEmpty()) {
                    throw new RuntimeException("Your stack is empty.");
                }
                return this.minStack.peek();
            }
        }
    
    
    }
    
    

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

  1. 思路
  • 准备两个队列,dataQueue队列和helpQueue队列;

  • 每次出栈时,只留下dataQueue中的最后一个元素,其余元素依次弹出到helpQueue队列中。此时dataQueue中剩余的最后一个元素即为栈顶元素,将其弹出即可。

    //用两个队列结构实现栈结构
    public class TwoQueueToStack {
    
        private Queue<Integer> queue;
        private Queue<Integer> help;
    
        public TwoQueueToStack(){
            queue = new LinkedList<Integer>();
            help = new LinkedList<Integer>();
        }
    
        //进栈
        public void push(int obj) {
            queue.add(obj);
        }
    
        //取栈顶元素
        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;
      }
    
    
    
    
      public void swap() {
          Queue temp;
          temp=queue;
          queue=help;
          help = temp;
      }
    

    }

    
    

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

  1. 思路:
  • 准备两个栈结构,pushStack栈和popStack栈。
  • 将pushStack栈中的数依次倒入popStack栈中,然后从popStack栈中出栈,即可实现队列结构
  1. 注意:
  • popStack栈中有数据的时候,不能向popStack中倒数据
  • 如果pushStack栈要向popStack栈中倒数据的话,那么一定要一次性倒完。
  1. 代码:

    //用两个栈结构实现队列结构
    public class TwoStackToQueue {
        private Stack<Integer> stackPush;
        private Stack<Integer> stackPop;
    
        public TwoStackToQueue() {
            stackPush = new Stack<>();
            stackPop = new Stack<>();
        }
    
        //进队
        public void push(int obj) {
            stackPush.push(obj);
        }
    
        //出队
        public int poll() {
            if (stackPush.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 (stackPush.empty() && stackPush.empty()) {
             throw new RuntimeException("Queue is empty!");
         } else if (stackPop.empty()) {
             while (!stackPush.empty()) {
                 stackPop.push(stackPush.pop());
             }
         }
    
         return stackPop.peek();
     }
    

    }

    
    
    
    

反转单向和双向链表

【题目】 分别实现反转单向链表和反转双向链表的函数。
【要求】 如果链表长度为N,时间复杂度要求为O(N),额外空间复杂度要求为O(1)

package class_03;

public class 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));

	}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值