剑指offer之栈与队列

队列是先进先出
栈是先进后出

  1. 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型
    栈1只用来存储数据

    分析: 弹出数据时:
    如果栈2无数据,栈1中的数据依次压入栈2中,然后栈2栈顶元素出栈
    如果栈2有数据,栈2栈顶元素出栈
    实现代码如下:

    public class TwoStackImplQueue {
    	Stack stack1 = new Stack();
    	Stack stack2 = new Stack();
    	
    	public void push(Integer element) {
    		stack1.push(element);
    	}
    	public 	Integer pop() {
    		if (stack2.size() <= 0) {
    			while (stack1.size() > 0) {
    				stack2.push(stack1.pop());
    			}
    		}
    		return stack2.pop();
    	}
    }
    
  2. 用两个队列来实现一个栈,完成栈的Push和Pop操作。 栈中的元素为int类型
    分析: 存储数据时利用一个队列来存储数据;弹出数据时,将有数据的队列中的数据依次出队列,放入另一个空队列中,将最后一个数据返回。总有一个队列是空的。
    代码如下:

    public class TwoQueueImplStack {
    		Queue queue1 = new ArrayDeque();
    		Queue queue2 = new ArrayDeque();
    		
    		public void push(Integer element) {
    			if (queue1.isEmpty() && queue2.isEmpty()) {
    				queue1.add(element);
    				return;
    			}
    			if (queue1.isEmpty()) {
    				queue2.add(element);
    				return;
    			}
    			if (queue2.isEmpty()) {
    				queue1.add(element);
    				return;
    			}
    		}
    		
    		public Integer pop() {
    			if (queue1.isEmpty()) {
    				while (queue2.size() > 1) {
    					queue1.add(queue2.poll());
    				}
    				return queue2.poll();
    			}
    			if(queue2.isEmpty()) {
    				while (queue1.size() > 1) {
    					queue2.add(queue1.poll());
    				}
    				return queue1.poll();
    			}
    			return null;
    		}
    	}
    
  3. 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
    分析: 利用一个数据栈和一个辅助栈来实现。
      存储数据时:初始时,数据栈和辅助栈均为空,数据栈和辅助栈均将数据进栈, 此时将唯一数据也就是栈顶数据认为是最小的数据元素。辅助栈不为空时,数据栈进栈,然后将数据与辅助栈栈顶元素比较,如果小于栈顶元素进栈,否则不进栈。
     弹出数据时:数据栈弹出数据,如果弹出的数据与辅助栈栈顶的数据相同,那么辅助栈同时也弹出数据,否则数据栈不作操作。

    这时,辅助栈的栈顶元素就是最小元素,返回它,时间复杂度为 O(1)。

    代码如下:

    public class Solution {
    
        Stack m_data = new Stack();
        Stack m_min = new Stack();
        public void push(int node) {
            m_data.push(node);
            if (m_min.empty()) {
                m_min.push(node);
            }else if (node <= m_min.peek()) {
                m_min.push(node);
            }
        }
        
        public void pop() {
            if (m_data.peek() == m_min.peek()) {
                m_min.pop();
            }
            m_data.pop();
        }
        
        public int top() {
            return m_data.peek();
        }
        
        public int min() {
            return m_min.peek();
        }
    }
    
  4. 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

    分析: 按照压栈和出栈顺序模拟栈的压栈和出栈过程,如果最后出栈结束,栈为空,则说明序列2为序列1的一个出战。

    代码如下:

    import java.util.ArrayList;
    import java.util.Stack;
    public class Solution {
        public boolean IsPopOrder(int [] pushA,int [] popA) {
            if (pushA == null || popA == null) {
                return false;
            }
            
            Stack s = new Stack();
            int spoint = 0;
            for (int i = 0; i < pushA.length; i++) {
                s.push(pushA[i]);
                while (!s.empty() && (s.peek() == popA[spoint])) {
                    s.pop();
                    spoint++;
                }
            }
            return s.empty();
        }
    }
    

思维扩展
元素个数 n 和总的出栈种类 f(n) 的关系:

f(0) = 1
f(1) = 1
f(2) = 2
f(3) = 5
f(n) = f(0)*f(n-1) + f(1)*f(n-2) + ....+ f(n-1)*f(0)

你可能感兴趣的:(数据结构与算法)