《算法(第四版)》1.3.45栈生成的可能性,练习题学习小结

栈的可能行。用例程序会进行一系列混合的入栈出栈操作,入栈操作按0,1,…,N-1的顺序进行,判断给定的排列是否是某系列混合出入栈操作的结果(你使用的空间量与N无关,即不能用某种数据结构存储所有整数)。

书中的提示:除非对于某个整数k,前k次出栈操作会在前k次入栈操作前完成,否则栈不会向下溢出。如果某个排列可以产生,那么它产生的方式一定是唯一的:如果输出排列中的下一个整数在栈顶,则将它弹出,否则将它压入栈中。而我设计的算法无需考虑(未考虑)下溢出的情况,可能有隐藏的错误。

思路a:设给定的乱序排列为(参考)栈refer,顺序排列为(输入)栈in,为即使出栈的整数被存储在栈buffer。成功出栈次数为printNum,打印结果为s。
1.匹配成功的数字会从顺序排列in中被直接弹出,否则会压入栈buffer。
2.每当排列in顶端元素匹配成功后,都要返回buffer查看是否存在与栈refer的下一个元素匹配的元素,若存在则基础此操作;若不存在,则返回操作1。
实现代码如下:

public class Exist {
	
	static Stack<Integer> in = new Stack<Integer>();  //0 1 2 3...
	static Stack<Integer> refer = new Stack<Integer>();  //乱序
	static Stack<Integer> buffer = new Stack<Integer>();
	static int printNum = 0;
	static String s = "";
	
	public static boolean bufferPop() {
		if(!buffer.isEmpty()) {
			if(buffer.top() == refer.top()) {
				printNum ++;
				buffer.pop();
				refer.pop();
				s = s + "-";
				bufferPop();
				return true;
			}
		}
		return false;
	}
	
	public static void bufferPush() {
		while(!in.isEmpty()) {
			int inNum = in.pop();
			int referNum = refer.top();
			s = s + inNum;
			if(inNum == referNum) {
				printNum ++;
				refer.pop();
				s = s + "-";
				bufferPop();
			} else {
				buffer.push(inNum);
			}
		}
		while(!refer.isEmpty() && bufferPop()) {
			bufferPop();
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		for(int i = 9; i >= 0; i --) {
			refer.push(Integer.parseInt(args[i]));
			in.push(i);
		}
		bufferPush();
		if(printNum == 10) {
			System.out.println(s);
		}
		
	}

}

bufferPop()函数和bufferPush函数存在相似的代码段,考虑是否能将此代码进行简化,删除杂糅的部分。

思路b:设给定的乱序排列为(参考)栈refer,顺序排列为(输入)栈in,为即使出栈的整数被存储在栈buffer。成功出栈次数为printNum,打印结果为s,上一次是否弹出成功标志位success。
1.根据书中的提示,栈in中的元素先考虑入栈到buffer。若buffer为空或buffer中上一次弹出不成功,则需要进行入栈。
2.buffer的顶端元素和栈refer顶端元素进行匹配,若匹配成功则从buffer中弹出此元素。重复这两步操作
实现代码如下:

public class MixUp {

	static Stack<Integer> in = new Stack<Integer>();  //0 1 2 3...
	static Stack<Integer> refer = new Stack<Integer>();  //乱序
	static Stack<Integer> buffer = new Stack<Integer>();  //未弹出缓存
	static int printNum = 0;  //“-”打印次数
	static String s = "";  //输出
	static boolean success = false;  //上一次是否弹出成功
	
	public static void bufferInOut() {
		while(!refer.isEmpty()) {
			if(!success || buffer.isEmpty()) {  //未成功弹出或buffer已空都要再次入栈
				buffer.push(in.pop());
				s = s + buffer.top();
			}
			int inNum = buffer.top();
			int referNum = refer.top();
			if(inNum == referNum) {
				printNum ++;
				refer.pop();
				s = s + "-";
				buffer.pop();
				success = true;
			} else
				success = false;
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		for(int i = 9; i >= 0; i --) {
			refer.push(Integer.parseInt(args[i]));
			in.push(i);
		}
		bufferInOut();
		if(printNum == 10) {
			System.out.println(s);
		}
		
	}

}

在这里插入图片描述
问题:题目要求“你使用的空间量与N无关,即不能用某种数据结构存储所有整数”,不清楚这里的“所有整数”的指代什么,且设计的算法使用空间量与N有关。但是这个算法是一个线性时间的算法。

《算法(第四版)》部分练习题索引

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值