《算法》1.3.3习题答案

113 阅读2分钟

1.3.3

假设某个用例程序会进行一系列入栈和出栈操作。入栈操作会将整数0到9按顺序压入栈;出栈操作会打印返回值。下面哪种顺序是不可能产生的?

(a)  4 3 2 1 0 9 8 7 6 5
(b)  4 6 8 7 5 3 2 9 0 1
(c)  2 5 6 7 4 8 9 3 1 0
(d)  4 3 2 1 0 5 6 7 8 9
(e)  1 2 3 4 5 6 9 8 7 0
(f)  0 4 6 5 3 8 1 7 2 9
(g)  1 4 7 9 8 6 5 3 0 2
(h)  2 1 4 3 6 5 8 7 9 0

方案一

分析:假设出入栈的就三个数 1,2,3,所有的情况数量是3的阶乘3!但仔细看其实其中一种情况是不满足的:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

即:3 1 2 是不可能的,首先输出3,说明1,2已经入栈,输出3后,2在栈顶,之后弹栈应该是2,所以这种情况不可能。
继而推广:“大 小 中 ”这种情况是不对的,由此可得选项中:(b)9 0 1、(f)8 1 7、 (g)3 0 2 这三种情况都是不可能出现的。

方案二

我们可以利用代码检测解决这个问题,既然这些序列(a,b...h)是从栈内输出的,那么建立一个辅助栈,将原来的0-9按照顺序入辅助栈,每次入栈时比较是否与待检测的序列元素(a,b...h)头节点相等,若相等则出栈,不相等则入栈,经过不断的入栈出栈,到最后辅助栈内应成为空栈,那么说明与要检测的序列对应上了,该序列合法,反之栈内留有元素则不合法。 那么咱们上代码:

/**
 * 解决方案二(其实与下面方案三大同小异)
 * 可以利用队列来或者用二维数组保存带检测的序列
 * @param testQueue 待检测的队列
 * @param originalQueue 原来将要入栈出栈等操作的队列
 * @return
 */
public static boolean isValid(Queue<String> testQueue, Queue<String>originalQueue){
    //检测序列是否合法
    check(testQueue,originalQueue);
    //利用队列来或者用二维数组保存带检测的序列
    //建立辅助栈
    Stack<String> stack = new Stack<>();
    //当前数列与待检测序列分别用一个队列来保存,
    Iterator<String> iterator = originalQueue.iterator();

    while (iterator.hasNext()){
        stack.push(iterator.next());
        while (!stack.isEmpty()&&stack.top().equals( testQueue.peek())){
            //出栈
            stack.pop();
            testQueue.dequeue();
        }
    }
    return stack.isEmpty();
    
    //test
  public static void main(String[] args){
    //"4 3 2 1 0 9 8 7 6 5";true
    String str = "0 4 6 5 3 8 1 7 2 9";
    String[] split = str.split("\s+");
    Queue<String> queue = new Queue<>();
    Queue<String> originalQueue = new Queue<>();
    for (String s : split){
        queue.enqueue(s);
    }
    for (int i = 0; i < 10;i++ ){
        originalQueue.enqueue(""+i);
    }
    System.out.println(isValid(queue, originalQueue));
}

方案三

因为需要判断的这些序列都是从栈内输出的,所以如果逆序再进栈出栈 应该是可以得到9-0的顺序(其实就是上面那种翻着来的),但是这个方法写的仅使用于当前问题。 上代码:

public static boolean isValid(int[] seq)
{
    Stack<Integer> stack = new Stack<Integer>();
    int currentNum = 9;
    int index = 9;
    while (currentNum >= 0)
    {
        if (index >= 0 && seq[index] == currentNum)
        {
            index--;
            currentNum--;
        }
        else if (!stack.isEmpty() && stack.top() == currentNum)
        {
            System.out.println(stack.pop());
            currentNum--;
        }
        else
        {
            if (index < 0)
                break;
            stack.push(seq[index]);
            index--;
        }
    }
    return stack.isEmpty();
}

public static void main(String[] args)
    {
        while (!StdIn.isEmpty())
        {
            String line = StdIn.readLine();
            String[] values = line.split("\\s+");
            int[] nums = new int[10];
 
            for (int i = 0; i < values.length; i++)
            {
                nums[i] = Integer.parseInt(values[i]);
            }
 
            if (isValid(nums))
            {
                System.out.println("OK");
            } 
            else
            {
                System.out.println("No");
            }
        }
    }