堆栈
用数组结构实现大小固定的队列和栈
-
用数组结构实现队列结构
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; } }
-
用数组结构实现栈结构
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]; } }
实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
- 【要求】
- pop、push、getMin操作的时间复杂度都是O(1)。
- 设计的栈类型可以使用现成的栈结构。
- 思路
- 准备两个栈,一个dataStack栈,一个minStack栈
- 当dataStack栈中压入第一个数时,minStack栈同时也压入第一个数;
- 之后当dataStack栈中每压入一个数时,将这个数和minStack栈的栈顶作比较,若当前数比minStack的栈顶小,则minStack栈压入当前数,否则将minStack的栈顶再压入一遍;
- 当出栈时,dataStack栈和minStack栈同步出栈即可;
- 代码
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(); } } }
如何仅用队列结构实现栈结构?
- 思路
-
准备两个队列,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; }
}
如何仅用栈结构实现队列结构?
- 思路:
- 准备两个栈结构,pushStack栈和popStack栈。
- 将pushStack栈中的数依次倒入popStack栈中,然后从popStack栈中出栈,即可实现队列结构
- 注意:
- popStack栈中有数据的时候,不能向popStack中倒数据
- 如果pushStack栈要向popStack栈中倒数据的话,那么一定要一次性倒完。
-
代码:
//用两个栈结构实现队列结构 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));
}
}