leetcode初级之设计问题

1. Shuffle an Array

打乱一个没有重复元素的数组。

解题思路:如果你从前向后遍历,遍历一次,然后选择目标位置和当前位置对换,看似足够随机,实则是错误的做法。这是为什么呢?
证明:这里并不需要多么深奥的数学知识,只需要高中所学的概率论的基础知识。当年有这样一道题:有n个球,随机放到n个格子,那么一共有多少种方法。题中抽象出来,不就是这个问题吗?应该怎么做?首先,从一堆球中随机选出一个放到1格中,然后从剩下的n-1个格子中选出一个放到2格中,依次类推,一共有n!种情况,这个是正确答案。
那么,当你在遍历到第i个格子时,依旧用rand()%nums.size()进行选择,那么你的程序可能获得的种类就是n^n中情况,多计算了n^n-n!情况,这根本就不是随机相同概率。
那么我们应该怎么?我们把这个数组单层空的格子,首先,我们要获取到第一个格子应该放的元素,从n个数中随机找一个,即数组下标为rand()%nums.size(),然后放到第一个格子中,第二个格子,我们就需要从n-1个数中随机找一个,即数组下标为1+rand()%(nums.size()-1),放到第二个格子中。
依次类推,
第i个格子应该放的元素是数组下标为i+rand()%(nums.size() -i)的数。
bingo,公式推导完毕。

public:
    Solution(vector nums): v(nums) {}
    
    /** Resets the array to its original configuration and return it. */
    vector reset() {
        return v;
    }
    
    /** Returns a random shuffling of the array. */
    vector shuffle() {
        if(0 >= v.size())//注意数组为空的情况。
            return v;
        vector res(v);
        for (int i = 0; i < res.size()-1; ++i) {
            int select = i + rand() % (res.size()-i);
            swap(res[i], res[select]);
        }
        return res;
    }
    
private:
    vector v;

2. 最小栈

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) -- 将元素 x 推入栈中。
pop() -- 删除栈顶的元素。
top() -- 获取栈顶元素。
getMin() -- 检索栈中的最小元素。

解题思路:需要参数时间内找到最小元素的栈,一个额外栈记录最小数,主栈中的最小数被pop,相应的记录栈中依然被pop,这时记录栈的栈顶的最小数依然是被pop的那个最小数出现之前的最小数。栈的最大功能就是记忆~

public:
    /** initialize your data structure here. */
    MinStack() {
    }
    
    void push(int x) {
        main.push(x);
        if(0 == min.size())
        {
            min.push(x);
            return ;
        }
        if(x<=min.top())
            min.push(x);
    }
    
    void pop() {
        if( main.top() == min.top())
            min.pop();
        main.pop();
    }
    
    int top() {
        return main.top();
    }
    
    int getMin() {
        return min.top();
    }
private:
    stack main;
    stack min;

你可能感兴趣的:(leetcode初级之设计问题)