Cracking the Coding Interview Q3.1

Describe how you could use a single array to implement three stacks.

思路1:fixed division

package Question3_1;

import java.util.EmptyStackException;

public class Question {
    static int stackSize = 10;
    static int [] buffer = new int [stackSize * 3];

    // 3 stack pointers to keep track of the index of the top element
    static int [] stackPointer = {-1, -1, -1};
    public static void main(String [] args) throws Exception  {
        push(2, 4);
        System.out.println("Peek 2: " + peek(2));
        push(0, 3);
        push(0, 7);
        push(0, 5);
        System.out.println("Peek 0: " + peek(0));
        pop(0);
        System.out.println("Peek 0: " + peek(0));
        pop(0);
        System.out.println("Peek 0: " + peek(0));
    }

    static void push(int stackNum, int value) throws Exception {
        /* Check that we have space for the next element */
        if (stackPointer[stackNum] + 1 >= stackSize) {
            throw new FullStackException();
        }
        /* Increment stack pointer and then update top value*/
        stackPointer[stackNum]++;
        buffer[absTopOfStack(stackNum)] = value;
    }

    static int pop(int stackNum) throws Exception {
        if (isEmpty(stackNum)) {
            throw new EmptyStackException();
        }
        int value = buffer[absTopOfStack(stackNum)]; // Get top
        buffer[absTopOfStack(stackNum)] = 0; // Clear index
        stackPointer[stackNum]--; // Decrement pointer
        return value;
    }

    static int peek(int stackNum) {
        if (isEmpty(stackNum)) {
            throw new EmptyStackException();
        }
        return buffer[absTopOfStack(stackNum)];
    }

    static boolean isEmpty(int stackNum) {
        return stackPointer[stackNum] == -1;
    }

    /* returns index of the top of the stack "stackNum", in absolute terms */
    static int absTopOfStack(int stackNum) {
        return stackNum * stackSize + stackPointer[stackNum];
    }
}

思路2:

package Question3_1;

import CtCILibrary.AssortedMethods;

public class QuestionB {
    static int number_of_stacks = 3;
    static int default_size = 4;
    static int total_size = default_size * number_of_stacks;
    static StackData [] stacks = {new StackData(0, default_size),
                                     new StackData(default_size, default_size),
                                     new StackData(default_size * 2, default_size)};
    static int [] buffer = new int [total_size];

    public static void main(String [] args) throws Exception  {
        push(0, 10);
        push(1, 20);
        push(2, 30);

        push(1, 21);
        push(0, 11);
        push(0, 12);

        pop(0);

        push(2, 31);

        push(0, 13);
        push(1, 22);

        push(2, 31);
        push(2, 32);
        push(2, 33);
        push(2, 34);

        System.out.println("Final Stack: " + AssortedMethods.arrayToString(buffer));

        pop(1);
        push(2, 35);

        System.out.println("Final Stack: " + AssortedMethods.arrayToString(buffer));
    }

    public static int numberOfElements() {
        return stacks[0].size + stacks[1].size + stacks[2].size;
    }

    public static int nextElement(int index) {
        if (index + 1 == total_size) {
            return 0;
        } else {
            return index + 1;
        }
    }

    public static int previousElement(int index) {
        if (index == 0) {
            return total_size - 1;
        } else {
            return index - 1;
        }
    }

    public static void shift(int stackNum) {
        StackData stack = stacks[stackNum];
        if (stack.size >= stack.capacity) {
            int nextStack = (stackNum + 1) % number_of_stacks;
            shift(nextStack); // make some room
            stack.capacity++;
        }
        for (int i = (stack.start + stack.capacity - 1) % total_size; // end of array
                      stack.isWithinStack(i, total_size);
                      i = previousElement(i)) {
            buffer[i] = buffer[previousElement(i)];
        }
        buffer[stack.start] = 0;
        stack.start = nextElement(stack.start); // move start start
        stack.pointer = nextElement(stack.pointer); // move stack pointer
        stack.capacity--; // return capacity to original
    }

    /* Expand stack by shifting over other stacks */
    public static void expand(int stackNum) {
        shift((stackNum + 1) % number_of_stacks);
        stacks[stackNum].capacity++;
    }

    static void push(int stackNum, int value) throws Exception {
        StackData stack = stacks[stackNum];
        /* Check that we have space */
        if (stack.size >= stack.capacity) {
            if (numberOfElements() >= total_size) { // Totally full
                throw new Exception("Out of space.");
            } else { // just need to shift things around
                expand(stackNum);
            }
        }
        /* Find the index of the top element in the array + 1,
         * and increment the stack pointer */
        stack.size++;
        stack.pointer = nextElement(stack.pointer);
        buffer[stack.pointer] = value;
    }

    static int pop(int stackNum) throws Exception {
        StackData stack = stacks[stackNum];
        if (stack.size == 0) {
            throw new Exception("Trying to pop an empty stack.");
        }
        int value = buffer[stack.pointer];
        buffer[stack.pointer] = 0;
        stack.pointer = previousElement(stack.pointer);
        stack.size--;
        return value;
    }

    static int peek(int stackNum) {
        StackData stack = stacks[stackNum];
        return buffer[stack.pointer];
    }

    static boolean isEmpty(int stackNum) {
        StackData stack = stacks[stackNum];
        return stack.size == 0;
    }
}

package Question3_1;

public class StackData {
    public int start;
    public int pointer;
    public int size = 0;
    public int capacity;
    public StackData(int _start, int _capacity) {
        start = _start;
        pointer = _start - 1;
        capacity = _capacity;
    }

    public boolean isWithinStack(int index, int total_size) {
        // Note: if stack wraps, the head (right side) wraps around to the left.
        if (start <= index && index < start + capacity) {
            // non-wrapping, or "head" (right side) of wrapping case
            return true;
        } else if (start + capacity > total_size &&
                   index < (start + capacity) % total_size) {
            // tail (left side) of wrapping case
            return true;
        }
        return false;
    }
}

Cracking the Coding Interview Q3.1,布布扣,bubuko.com

时间: 2024-08-24 07:25:59

Cracking the Coding Interview Q3.1的相关文章

《Cracking the Coding Interview》——第16章:线程与锁——题目5

2014-04-27 20:16 题目:假设一个类Foo有三个公有的成员方法first().second().third().请用锁的方法来控制调用行为,使得他们的执行循序总是遵从first.second.third的顺序. 解法:你应该想到了用lock的方法类阻塞,不过这里面有个概念问题使得直接用ReentrantLock不能通过编译(对于一个锁对象,不同在A线程中锁定,又在B线程中解锁,不允许这样的归属关系),可以用Semaphore来达到相同的目的.请看下面的代码. 代码: 1 // 16

《Cracking the Coding Interview》——第16章:线程与锁——题目3

2014-04-27 19:26 题目:哲学家吃饭问题,死锁问题经典模型(专门用来黑哲学家的?). 解法:死锁四条件:1. 资源互斥.2. 请求保持.3. 非抢占.4. 循环等待.所以,某砖家拿起一只筷子后如果发现没有另一只了,就必须把手里这只筷子放下,这应该是通过破坏"请求保持"原则来防止死锁产生,请求资源失败时,连自己的资源也进一步释放,然后在下一轮里继续请求,直到成功执行. 代码: 1 // This is the class for chopsticks. 2 import j

《Cracking the Coding Interview》——第16章:线程与锁——题目2

2014-04-27 19:14 题目:如何测量上下文切换的时间? 解法:首先,上下文切换是什么,一搜就知道.对于这么一个极短的时间,要测量的话,可以通过放大N倍的方法.比如:有A和B两件事,并且经常一起发生,每件只需要花几纳秒.如果你把A事件连续做几百万次,而B时间只做了几次,这样就能排除B事件对于测量的影响.如果总时间S = mA + nB.当m >> n 时,A≈S / m.下面的测量方法类似于打乒乓球,在主线程和副线程间互相传递一个令牌,这个令牌可以是变量.管道之类的用于通信的工具.与

《Cracking the Coding Interview》——第16章:线程与锁——题目1

2014-04-27 19:09 题目:线程和进程有什么区别? 解法:理论题,操作系统教材上应该有很详细的解释.我回忆了一下,写了如下几点. 代码: 1 // 16.1 What is the difference between process and thread? 2 Answer: 3 Process: 4 1. Basic element of resource allocation in the operating system. 5 2. Possesses independent

《Cracking the Coding Interview》——第18章:难题——题目10

2014-04-29 04:22 题目:给定一堆长度都相等的单词,和起点.终点两个单词,请从这堆单词中寻找一条变换路径,把起点词变成终点词,要求每次变换只能改一个字母. 解法:Leetcode中有Word Ladder,这题基本思路一致. 代码: 1 // 18.10 Given a list of words, all of same length. Given a source and a destionation words, you have to check if there exis

《Cracking the Coding Interview》——第18章:难题——题目9

2014-04-29 04:18 题目:有一连串的数被读入,设计一个数据结构,能随时返回当前所有数的中位数. 解法:用一个大顶堆,一个小顶堆将数分成数量最接近的两份,就能轻松得到中位数了. 代码: 1 // 18.9 A stream of integers are passed to you, you have to tell me the median as they keep coming in. 2 #include <climits> 3 #include <iostream&

《Cracking the Coding Interview》——第18章:难题——题目13

2014-04-29 04:40 题目:给定一个字母组成的矩阵,和一个包含一堆单词的词典.请从矩阵中找出一个最大的子矩阵,使得从左到右每一行,从上到下每一列组成的单词都包含在词典中. 解法:O(n^3)级别的时间和空间进行动态规划.这道题目和第17章的最后一题很像,由于这题的时间复杂度实在是高,我动手写了字典树进行加速.如果单纯用哈希表来作为词典,查询效率实际会达到O(n)级别,导致最终的算法复杂度为O(n^4).用字典树则可以加速到O(n^3),因为对于一个字符串"abcd",只需要

《Cracking the Coding Interview》——第18章:难题——题目11

2014-04-29 04:30 题目:给定一个由'0'或者'1'构成的二维数组,找出一个四条边全部由'1'构成的正方形(矩形中间可以有'0'),使得矩形面积最大. 解法:用动态规划思想,记录二维数组每个元素向上下左右四个方向各有多少个连续的'1',然后用O(n^3)时间计算出满足条件的最大正方形.时间复杂度O(n^3),空间复杂度O(n^2). 代码: 1 // 18.11 Given an NxN matrix of 0s and 1s, find out a subsquare whose

《Cracking the Coding Interview》——第18章:难题——题目12

2014-04-29 04:36 题目:最大子数组和的二位扩展:最大子矩阵和. 解法:一个维度上进行枚举,复杂度O(n^2):另一个维度执行最大子数组和算法,复杂度O(n).总体时间复杂度为O(n^3),还需要O(n)额外空间. 代码: 1 // 18.12 Given an n x n matrix, find the submatrix with largest sum. Return the sum as the result. 2 #include <algorithm> 3 #inc