关于模拟盘子的堆栈实现(Crack the interview 例题)之暑假学习记录

这两天,可能运动量过大,每天很是昏昏沉沉。今天写一个例题程序,自以为很容易就搞定,没想到墨墨迹迹搞了一个多小时。可见精神状态也很重要,但同时也发现了一些自己关于java的问题。这篇文章只为记录今天垃圾的状态,如果有朋友有兴趣去看这道题目,可以拿走。

题目大致是这样的:

模拟实现一组盘子,盘子的原理就是堆栈原理,那么为了不使盘子因过高而摔碎,我们可以给盘子分组,每一组是N个。但是拿取盘子的方式还是按照堆栈的方式实现,即先进后出(FILO)。 这道题目的有意思之处在于,如何在指定的分组中用FILO的方式取盘子并且保证盘子序号左对齐。(这句主要我不知道怎么翻译好,给大家举个例子就明白了)

分组1:a, b, c 

分组2:d, e, f

分组3: g, h ,i

如果从分组1中pop一个元素,那么整个分组变成:

分组1:a, b, d 

分组2:e, f, g

分组3: h ,i

如果分组一直在分组1中pop的话,那么分组3可能会成一个空元素分组,那么删除此分组。

看到这里大家估计都有想法了,是的,这个不难。但是我的思路可能不够精妙,如果大家有新的建议,欢迎留言。

1. 题目分析:

思路1:如果把每个分组严格按照栈去操作,FILO,可以搞定。但是时间复杂度太大。因为每个元素的pop都需要移动n个元素,非常耗时。

思路2:如果把分组当作队列处理,是不是就可以满足这类操作呢?是的,但是这破坏了本身分组操作的手段。在我们push的时候,方便,在pop的时候就麻烦了。

思路3:把这个当作栈,但是用链表实现,基本操作还是FILO,但是在指定分组pop的操作,用队列的原理实现。这并不违背堆栈的操作意义。而下面代码就是根据这种思想写的。这样的话每次pop操作的时间复杂度在O(1),完全达到要求。

废话不多说,上代码:

import java.util.LinkedList;


public class SetsOfStack3 {
	LinkedList<Stack> s;
	int capacity;
	public SetsOfStack3(int num){
		s = new LinkedList<Stack>();
		s.add(new Stack());
		this.capacity = num;
	}
	public void push(int value){
		Stack last = s.getLast();
		if(last!=null && last.size() < this.capacity){
			last.push(value);
		}else{
			s.add(new Stack());
			s.getLast().push(value);
		}
	}
	public int pop(){
		int value = 0;
		Stack last = s.getLast();
		value = last.pop();
		if(last.size() == 0)
			s.removeLast();
		return value;
	}
	public static void printStack1s(LinkedList<Stack> list){
		System.out.println("--------------------------------------");
		for(int i = 0; i<list.size();i++){
			System.out.println("Stack"+(i+1)+" is : ");
			for(int j=0;j<list.get(i).size();j++){
				System.out.print(list.get(i).get(j)+ " ");
			}
			System.out.println();
		}
		System.out.println("\n--------------------------------------");
	}
	public int popAt(int index){
		int value = 0;
		if(index >= s.size()){
			System.out.println("Non-existed index");
			return -1;
		}
		else if(index + 1 >= s.size()){
			value = this.pop();
		}
		else{
			Stack current = s.get(index);
			Stack next = current;
			value = current.pop();
			while(++index < s.size()){
				next = s.get(index);
				current.rollOver(next);
				current = next;
				if(s.getLast().size() == 0 )
					s.removeLast();
			}
			}
		return value;
	}
	public static void main(String[] args){
		SetsOfStack3 s = new SetsOfStack3(3);
		s.push(1);
		s.push(2);
		s.push(3);
		s.push(4);
		s.push(5);
		s.push(6);
		s.push(7);
		s.push(8);
		s.push(9);
		s.push(10);
		s.push(15);
		s.push(20);
		printStack1s(s.s);
		System.out.println("pop at 1: "+s.popAt(0));
		printStack1s(s.s);
		System.out.println("pop at 2: "+s.popAt(1));
		printStack1s(s.s);
		System.out.println("pop at 2: "+s.popAt(1));
		printStack1s(s.s);
	}
}
 class Stack{
	LinkedList<Integer> list;
	public Stack(){
		list = new LinkedList<Integer>();
	}
	void push(int value){
		list.add(value);
	}
	int pop(){
		return list.removeLast();
	}
	int size(){
		return list.size();
	}
	int getFirst(){
		return list.getFirst();
	}
	int getLast(){
		return list.getLast();
	}
	int pollFirst(){
		return list.poll(); 
	}
	int get(int index){
		return list.get(index);
	}
	void rollOver(Stack test){
		 list.add(test.pollFirst());
	}
}


这个代码是在我调试version1的代码一个小时后,愤怒删除后,从新start from scratch 写的,效果不错。这证明当思路紊乱的时候,打碎重写不失为一种好办法。

为了忘却而纪念今天的垃圾状态。阿弥陀佛上帝保佑阿门阿门。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值