算法-第四版-练习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

分析3个数时的入栈与出栈操作,所有的顺序有3!种。分别为:

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

解法一

可以知道只有 3 1 2 这种顺序不可能的,将其推广就可以得到这种的规律:

大 小 中

这种顺序是不能出现的。

如上述中(b)中的9 0 1,(f)中的8 1 7,(g)中的3 0 2。所以b, f, g是不能产生的。

解法二

本文采用另一种思路来解决这个问题。

就假设上述都是合法序列,即都是由出栈产生的,那么应该能将些序列作为出入通过入栈与出栈操作,得到一个顺序的序列。

而问题在于入栈的方向、与得到顺序序列是升序还是降序呢?

显然逆过程应该是从上述输出的尾部开始入栈,而得到的序列应该也是逆序的。以(a)为例,从5开始入栈,一直到4。要得到9 8...1 0的序列。

下面给出实现的代码,首先需要给Stack添加一个top()方法。

/**
 * Description : 
 * Author      : mn@furzoom.com
 * Date        : Sep 27, 2016 5:07:34 PM
 * Copyright (c) 2013-2016, http://furzoom.com All Rights Reserved.
 */
package com.furzoom.lab.algs.ch103;

import java.util.Iterator;

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

/**
 * ClassName    : Stack <br>
 * Function     : TODO ADD FUNCTION. <br>
 * date         : Sep 27, 2016 5:07:34 PM <br>
 * 
 * @version 
 */
public class Stack<Item> implements Iterable<Item>
{
    private Node first;
    private int n;
    private class Node
    {
        Item item;
        Node next;
    }
        
    public boolean isEmpty() 
    {
        return first == null;
    }
    
    public int size()
    {
        return n;
    }
    
    public void push(Item item)
    {
        Node oldfirst = first;
        first = new Node();
        first.item = item;
        first.next = oldfirst;
        n++;
    }
    
    public Item pop()
    {
        Item item = first.item;
        first = first.next;
        n--;
        return item;
    }
    
    public Item top()
    {
        return first.item;
    }
       
    @Override
    public Iterator<Item> iterator()
    {
        return new ReverseArrayIterator();
    }
    
    private class ReverseArrayIterator implements Iterator<Item>
    {
        private Node p = first;
        @Override
        public boolean hasNext()
        {
            return p != null;
        }

       @Override
        public Item next()
        {
           Item item = p.item;
           p = p.next;
           return item;
        }
        
    }

    public static void main(String[] args)
    {
        Stack<String> s;
        s = new Stack<String>();
        while (!StdIn.isEmpty())
        {
            String item = StdIn.readString();
            if (!item.equals("-"))
                s.push(item);
            else if (!s.isEmpty())
                StdOut.print(s.pop() + " ");
        }
        StdOut.println("(" + s.size() + " left on stack)");
    }
}

测试用例:

/**
 * Description : 
 * Author      : mn@furzoom.com
 * Date        : Sep 28, 2016 2:25:18 PM
 * Copyright (c) 2013-2016, http://furzoom.com All Rights Reserved.
 */
package com.furzoom.lab.algs.ch103;

import edu.princeton.cs.algs4.StdIn;

/**
 * ClassName    : E10303 <br>
 * Function     : TODO ADD FUNCTION. <br>
 * date         : Sep 28, 2016 2:25:18 PM <br>
 * 
 * @version 
 */
public class E10303
{
    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)
            {
                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");
            }
        }
    }

}

结果如下 :

>java -cp ".;../lib/algs4.jar" com
.furzoom.lab.algs.ch103.E10303 < com/furzoom/lab/algs/ch103/E10303.txt
OK
No
OK
OK
OK
No
No
OK

测试数据文件 E10303.txt为:

4 3 2 1 0 9 8 7 6 5
4 6 8 7 5 3 2 9 0 1
2 5 6 7 4 8 9 3 1 0
4 3 2 1 0 5 6 7 8 9
1 2 3 4 5 6 9 8 7 0
0 4 6 5 3 8 1 7 2 9
1 4 7 9 8 6 5 3 0 2
2 1 4 3 6 5 8 7 9 0



算法-第四版-1.3 背包、队列和栈-习题索引汇总

算法-第四版习题索引汇总

作者:马 岩Furzoom) (http://www.cnblogs.com/furzoom/
版权声明:本文的版权归作者与博客园共同所有。转载时请在明显地方注明本文的详细链接,未经作者同意请不要删除此段声明,感谢您为保护知识产权做出的贡献。
原文地址:https://www.cnblogs.com/furzoom/p/7710207.html