• 数据结构之栈和队列


    这次,我们主要看栈和队列的相关题目。

      栈是“后进先出”的数据结构,队列是“先进先出”的数据结构,我们假设栈和队列中存储的都是整型数值,先来定义这两种数据结构(都采用数组的形式来存储信息,当达到数组边界时,对数组进行扩容处理)。

      栈主要包括Push、Pop和Peek和Count三个方法,如下:

     
     1 public class Stack {
     2     private int[] arrValue = null;
     3     private int m_Capacity;
     4     private int m_Count;
     5     private void set_Count(int m_Count) {
     6         this.m_Count = m_Count;
     7     }
     8 
     9     public int get_Count() {
    10         return m_Count;
    11     }
    12     
    13     public Stack(int capacity)
    14     {
    15         m_Capacity = capacity;
    16         arrValue = new int[capacity];
    17         set_Count(0);
    18     }
    19     
    20     public void push(int value)
    21     {
    22         if (get_Count() == m_Capacity)
    23         {
    24             System.out.println("Need to malloc more space for stack.");
    25             int[] temp = new int[m_Capacity*2];
    26             for(int i = 0; i < m_Capacity; i++)
    27             {
    28                 temp[i] = arrValue[i];
    29             }
    30             arrValue = temp;
    31             m_Capacity = m_Capacity*2;
    32             System.out.println("The capacity of stack is " + m_Capacity);
    33         }
    34         set_Count(get_Count() + 1);
    35         arrValue[get_Count() - 1] = value;
    36         
    37     }
    38     
    39     public int peek()
    40     {
    41         if (get_Count() == 0)
    42         {
    43             System.out.println("Stack is empty;");
    44             return Integer.MIN_VALUE;
    45         }
    46         return arrValue[get_Count() - 1];
    47     }
    48     
    49     public int pop()
    50     {
    51         if (get_Count() == 0)
    52         {
    53             System.out.println("Stack is empty;");
    54             return Integer.MIN_VALUE;
    55         }
    56         int result = arrValue[get_Count() - 1];
    57         set_Count(get_Count() - 1);
    58         return result;
    59     }
    60 }
     

      队列主要包括EnQueue和DeQueue两个方法,如下:

     
     1 public class Queue {
     2     private int m_Capacity;
     3     private int m_Count;
     4     private int[] m_arrValue;
     5     
     6     public Queue(int capacity)
     7     {
     8         m_Capacity = capacity;
     9         m_arrValue = new int[capacity];
    10         set_Count(0);
    11     }
    12     
    13     public void enQueue(int value)
    14     {
    15         if (get_Count() == m_Capacity)
    16         {
    17             System.out.println("Need to malloc more space for queue.");
    18             int[] temp = new int[m_Capacity*2];
    19             for(int i = 0; i < m_Capacity; i++)
    20             {
    21                 temp[i] = m_arrValue[i];
    22             }
    23             m_arrValue = temp;
    24             m_Capacity = m_Capacity*2;
    25             System.out.println("The capacity of queue is " + m_Capacity);
    26         }
    27         set_Count(get_Count() + 1);
    28         m_arrValue[get_Count() - 1] = value;
    29     }
    30     
    31     public int deQueue()
    32     {
    33         if(get_Count() == 0)
    34         {
    35             System.out.println("The queue is empty.");
    36             return Integer.MIN_VALUE;
    37         }
    38         int result = m_arrValue[0];
    39         for (int i = 1; i < get_Count(); i++)
    40         {
    41             m_arrValue[ i - 1] = m_arrValue[i];
    42         }
    43         set_Count(get_Count() - 1);
    44         return result;
    45     }
    46 
    47     private void set_Count(int m_Count) {
    48         this.m_Count = m_Count;
    49     }
    50 
    51     public int get_Count() {
    52         return m_Count;
    53     }
    54 }
     

      下面,我们来看和这两种数据类型相关的题目。

    • 设计含有min函数的栈,要求min、push和pop的时间复杂度是O(1)。 思路:使用一个栈来实现上述要求,在栈顶保存min()值,每次Push或者Pop,向栈操作两次,第一次针对min,第二次是实际的值,这样我们可以使用Peek方法来取得min值。
       
       1 public class NewStack {
       2     private int[] m_arrValue = null;
       3     private int m_Capacity;
       4     private int m_Count;
       5     
       6     public NewStack(int capacity)
       7     {
       8         m_arrValue = new int[2*capacity];
       9         m_Capacity = 2*capacity;
      10         m_Count = 0;
      11     }
      12     
      13     public void push(int value)
      14     {
      15         if (m_Count * 2 + 2 > m_Capacity)
      16         {
      17             System.out.println("Need to malloc more space for stack.");
      18             int[] temp = new int[m_Capacity*2];
      19             for(int i = 0; i < m_Capacity; i++)
      20             {
      21                 temp[i] = m_arrValue[i];
      22             }
      23             m_arrValue = temp;
      24             m_Capacity = m_Capacity*2;
      25             System.out.println("The capacity of stack is " + m_Capacity/2);
      26         }
      27         int min = Integer.MAX_VALUE;
      28         if (m_Count > 0)
      29         {
      30             min = m_arrValue[2*m_Count - 1];
      31         }        
      32         m_Count++;
      33         m_arrValue[2*m_Count -2] = value;
      34         m_arrValue[2*m_Count - 1] = min < value ? min : value;
      35     }
      36     
      37     public int peek()
      38     {
      39         if (m_Count == 0)
      40         {
      41             System.out.println("stack is empty.");
      42             return Integer.MIN_VALUE;
      43         }
      44         return m_arrValue[2*m_Count - 2];
      45     }
      46     
      47     public int min()
      48     {
      49         if (m_Count == 0)
      50         {
      51             System.out.println("stack is empty.");
      52             return Integer.MIN_VALUE;
      53         }
      54         return m_arrValue[2*m_Count - 1];
      55     }
      56     
      57     public int pop()
      58     {
      59         if (m_Count == 0)
      60         {
      61             System.out.println("stack is empty.");
      62             return Integer.MIN_VALUE;
      63         }
      64         int result = m_arrValue[2*m_Count - 2];
      65         m_Count--;
      66         return result;
      67     }
      68 
      69     public void set_Count(int m_Count) {
      70         this.m_Count = m_Count;
      71     }
      72 
      73     public int get_Count() {
      74         return m_Count;
      75     }
      76 }
       

      上述代码是从头开始实现的栈,包括对存储结构的处理细节,我们可以看上面关于Stack的定义,其实已经包括了这些细节,因此我们可以直接拿来用,代码会更清晰。

       
       1 public class NewStack2 {
       2     private Stack stack;
       3     
       4     public NewStack2(int capacity)
       5     {
       6         stack = new Stack(capacity*2);
       7     }
       8     
       9     public void push(int value)
      10     {
      11         if(stack.get_Count() == 0)
      12         {
      13             stack.push(value);
      14             stack.push(value);
      15         }
      16         else
      17         {
      18             int min = stack.peek();
      19             stack.push(value);
      20             stack.push(value > min ? min : value);
      21         }
      22     }
      23     
      24     public int min()
      25     {
      26         return stack.peek();
      27     }
      28     
      29     public int pop()
      30     {
      31         stack.pop();
      32         return stack.pop();
      33     }
      34     
      35     public int get_Count()
      36     {
      37         return stack.get_Count()/2;
      38     }
      39 }
       
    • 用两个栈实现一个队列 思路:两个栈一个作为入值栈,一个作为出值栈,当执行Push操作时,将值压入入值栈,当执行Pop或者Peek操作时,取出值栈的栈顶元素,当出值栈为空时,需要将入值栈的元素依次压入出值栈。
       
       1 public class NewQueue {
       2     private Stack inStack;
       3     private Stack outStack;
       4     
       5     public NewQueue(int capacity)
       6     {
       7         inStack = new Stack(capacity);
       8         outStack = new Stack(capacity);
       9     }
      10     
      11     public void enQueue(int value)
      12     {
      13         inStack.push(value);
      14     }
      15     
      16     public int deQueue()
      17     {
      18         if(inStack.get_Count() == 0 && outStack.get_Count() == 0)
      19         {
      20             System.out.println("The queue is empty.");
      21             return Integer.MIN_VALUE;
      22         }
      23         if (outStack.get_Count() == 0)
      24         {
      25             while(inStack.get_Count() > 0)
      26             {
      27                 outStack.push(inStack.pop());
      28             }
      29         }
      30         return outStack.pop();
      31     }
      32     
      33     public int get_Count()
      34     {
      35         return inStack.get_Count() + outStack.get_Count();
      36     }
      37 }
       
    • 用两个队列实现一个栈 思路:根据“后进先出”和“先进后出”的特点,在运行过程中,其中一个队列应该一直为空,对于push操作,将值放到非空队列中,当进行Push或者Pop操作时,先将非空队列全部导入空队列,然后此时的非空队列的头元素就是我们期望的元素。
       
       1 public class NewStack3 {
       2 
       3     private Queue queue1;
       4     private Queue queue2;
       5     
       6     public NewStack3(int capacity)
       7     {
       8         queue1 = new Queue(capacity);
       9         queue2 = new Queue(capacity);
      10     }
      11     
      12     public void push(int value)
      13     {
      14         if (queue1.get_Count() == 0)
      15         {
      16             queue2.enQueue(value);
      17         }
      18         else
      19         {
      20             queue1.enQueue(value);
      21         }
      22     }
      23     
      24     public int peek()
      25     {
      26         if (queue1.get_Count() == 0 && queue2.get_Count() == 0)
      27         {
      28             System.out.println("The stack is empty.");
      29             return Integer.MIN_VALUE;
      30         }
      31         int result = Integer.MIN_VALUE;
      32         if (queue1.get_Count() > 0 && queue2.get_Count() == 0)
      33         {
      34             while(queue1.get_Count() > 1)
      35             {
      36                 queue2.enQueue(queue1.deQueue());
      37             }
      38             result = queue1.deQueue();
      39             queue2.enQueue(result);
      40         }
      41         else if (queue1.get_Count() == 0 && queue2.get_Count() > 0)
      42         {
      43             while(queue2.get_Count() > 1)
      44             {
      45                 queue1.enQueue(queue2.deQueue());
      46             }
      47             result = queue2.deQueue();
      48             queue1.enQueue(result);
      49         }
      50         
      51         return result;
      52     }
      53     
      54     public int pop()
      55     {
      56         if (queue1.get_Count() == 0 && queue2.get_Count() == 0)
      57         {
      58             System.out.println("The stack is empty.");
      59             return Integer.MIN_VALUE;
      60         }
      61         int result = Integer.MIN_VALUE;
      62         if (queue1.get_Count() > 0 && queue2.get_Count() == 0)
      63         {
      64             while(queue1.get_Count() > 1)
      65             {
      66                 queue2.enQueue(queue1.deQueue());
      67             }
      68             result = queue1.deQueue();
      69         }
      70         else if (queue1.get_Count() == 0 && queue2.get_Count() > 0)
      71         {
      72             while(queue2.get_Count() > 1)
      73             {
      74                 queue1.enQueue(queue2.deQueue());
      75             }
      76             result = queue2.deQueue();
      77         }
      78         
      79         return result;
      80     }
      81     
      82     public int get_Count()
      83     {
      84         return queue1.get_Count() + queue2.get_Count();
      85     }
      86 }
       
    • 递归反转一个栈,要求不能重建一个新栈,空间复杂度为O(1)。 思路:参考汉诺塔的递归思路。
       
       1 public static void Reverse(Stack stack)
       2 {
       3     if (stack.get_Count() == 0)
       4     {
       5         return;
       6     }
       7     int value1 = stack.pop();
       8     Reverse(stack);
       9     if (stack.get_Count() == 0)
      10     {
      11         stack.push(value1);
      12         return;
      13     }
      14     int value2 = stack.pop();
      15     Reverse(stack);
      16     stack.push(value1);
      17     Reverse(stack);
      18     stack.push(value2);
      19 }
       
    • 对栈进行排序 思路:依旧采取递归的套路
       
       1 public static void sort(Stack stack)
       2 {
       3     if (stack.get_Count() == 0)
       4     {
       5         return;
       6     }
       7     int value1 = stack.pop();
       8     sort(stack);
       9     if (stack.get_Count() == 0)
      10     {
      11         stack.push(value1);
      12         return;
      13     }
      14     int value2 = stack.pop();
      15     if (value1 > value2)
      16     {
      17         stack.push(value1);
      18         sort(stack);
      19         stack.push(value2);
      20     }
      21     else
      22     {
      23         stack.push(value2);
      24         sort(stack);
      25         stack.push(value1);
      26     }
      27 }
       
    • 判断栈的push、pop序列是否一致 思路:创建一个新栈,依次将push队列中的值压入,在压入过程中,判断pop队列,如果找到相同的值,执行stack.pop操作,以此类推,最终判断stack是否为空。
       
       1 public static boolean isMatch(int[] arrPush, int[] arrPop)
       2 {
       3     if (arrPush == null || arrPop == null || arrPush.length != arrPop.length)
       4     {
       5         return false;
       6     }
       7     Stack stack = new Stack(arrPush.length);        
       8     for(int i = 0, j = 0; i < arrPush.length; i++)
       9     {
      10         stack.push(arrPush[i]);
      11         while(j < arrPop.length)
      12         {
      13             if (stack.peek() == arrPop[j])
      14             {
      15                 stack.pop();
      16                 j++;
      17             }
      18             else
      19             {
      20                 break;
      21             }
      22         }
      23     }
      24     
      25     return stack.get_Count() == 0;
      26 }
       
    • 如何用一个数组实现两个栈 思路:用0、2、4、6……表示第一个栈的元素,用1、3、5、7表示第二个栈的元素
       
        1 public class NewStack4 {
        2     private int[] arrValue;
        3     private int capacity;
        4     private int m_Count1;
        5     private int m_Count2;
        6     
        7     public NewStack4(int capacity)
        8     {
        9         arrValue = new int[capacity];
       10         this.capacity = capacity;
       11         m_Count1 = 0;
       12         m_Count2 = 0;
       13     }
       14     
       15     public void push(int value, int type)
       16     {
       17         boolean bExtend = false;
       18         if (type == 1)
       19         {
       20             if (m_Count1 * 2 + 1 >= capacity)
       21             {
       22                 bExtend = true;
       23             }
       24         }
       25         if (type == 2)
       26         {
       27             if (m_Count2 * 2 + 2 >= capacity)
       28             {
       29                 bExtend=true;
       30             }
       31         }
       32         if (bExtend)
       33         {
       34             int[] temp = new int[capacity*2];
       35             capacity = capacity*2;
       36             for(int i = 0; i < arrValue.length; i++)
       37             {
       38                 temp[i] = arrValue[i];
       39             }
       40             arrValue = temp;
       41         }
       42         
       43         if (type == 1)
       44         {
       45             m_Count1++;
       46             arrValue[m_Count1*2 - 1] = value;
       47         }
       48         
       49         if (type == 2)
       50         {
       51             m_Count2++;
       52             arrValue[m_Count2*2] = value;
       53         }
       54     }
       55     
       56     public int peek(int type)
       57     {
       58         if (type == 1)
       59         {
       60             if (m_Count1 == 0)
       61             {
       62                 System.out.println("Stack 1 is empty.");
       63                 return Integer.MIN_VALUE;
       64             }
       65             else
       66             {
       67                 return arrValue[m_Count1*2 - 1];
       68             }
       69         }        
       70         if (type == 2)
       71         {
       72             if (m_Count2 == 0)
       73             {
       74                 System.out.println("Stack 1 is empty.");
       75                 return Integer.MIN_VALUE;
       76             }
       77             else
       78             {
       79                 return arrValue[m_Count2*2];
       80             }
       81         }
       82         
       83         return Integer.MIN_VALUE;
       84     }
       85     
       86     public int pop(int type)
       87     {
       88         if (type == 1)
       89         {
       90             if (m_Count1 == 0)
       91             {
       92                 System.out.println("Stack 1 is empty.");
       93                 return Integer.MIN_VALUE;
       94             }
       95             else
       96             {
       97                 int result = arrValue[m_Count1*2 - 1];
       98                 m_Count1--;
       99                 return result;
      100             }
      101         }        
      102         if (type == 2)
      103         {
      104             if (m_Count2 == 0)
      105             {
      106                 System.out.println("Stack 1 is empty.");
      107                 return Integer.MIN_VALUE;
      108             }
      109             else
      110             {
      111                 int result =arrValue[m_Count2*2];
      112                 m_Count2--;
      113                 return result;
      114             }
      115         }
      116         
      117         return Integer.MIN_VALUE;
      118     }
      119     
      120     public int get_Count(int type)
      121     {
      122         if (type == 1)
      123         {
      124             return m_Count1;
      125         }
      126         else if (type == 2)
      127         {
      128             return m_Count2;
      129         }
      130         return Integer.MIN_VALUE;
      131     }
      132     
      133 }
       

      这种方式在两个栈的容量接近时比较好,如果两个栈的容量相差很大, 那么会浪费很多存储空间。针对这个问题的解决方法是用0、1、2、3……表示第一个栈,用n、n-1、n-2、n-3……表示第二个栈,代码实现类似,这种情况下也可以对数组进行扩容。

        

      最后,欢迎大家提出更多相关的面试题目,我们可以一起讨论。

  • 相关阅读:
    互联网改变的产业 汽车 x 互联网 = 汽车革命
    我有一个实现HMI触摸屏的资源【4418开发平台】降d成本
    iTOP-4412开发板裸机开发环境文档分享
    2019年最受欢迎iTOP-4418开发板_新产品研发必备利器
    安卓触控一体机为什么得到大家认可?远比Windows系统一体机大受欢迎
    新手入门嵌入式学习单片机?stm32?树莓派?4412开发板资料大汇报-基础了解
    iTOP-4418开发板-Qt系统下运行摄像头测试程序
    iTOP-4418/6818开发板-QtE4.7WIFI_MT6620热点
    iTOP-4412开发板-使用PartitionManager分区之后tf卡无法识别
    迅为iTOP-4418/6818开发板-MiniLinux-GPS使用文档
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3444635.html
Copyright © 2020-2023  润新知