leetcode : Permutations I&II

I:

Given a collection of numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2], and [3,2,1].

II:

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2][1,2,1], and [2,1,1].

I的AC代码:

class Solution {
public:
    vector<vector<int> > permute(vector<int> &num) {
        vector<bool> visited(num.size(), false);
        vector<vector<int>> ret;
        vector<int> path;
        dfs(num, visited, ret, path);
        return ret;
    }
    void dfs(vector<int> &num, vector<bool> &visited, vector<vector<int>> &ret, vector<int> &path){
        bool completed = true;
        for(int i = 0; i < num.size(); ++i){
            if(!visited[i]){
                path.push_back(num[i]);
                visited[i] = true;
                dfs(num, visited, ret, path);
                visited[i] = false;
                path.erase(--path.end());
                completed = false;
            }
        }
        if(completed)
            ret.push_back(path);
    }
};

II的AC代码:

class Solution {
public:
    vector<vector<int> > permuteUnique(vector<int> &num) {
        sort(num.begin(), num.end());
        vector<bool> visited(num.size(), false);
        vector<vector<int>> ret;
        vector<int> path;
        dfs(num, visited, ret, path);
        return ret;
    }
    void dfs(vector<int> &num, vector<bool> visited, vector<vector<int>> &ret, vector<int> path){
        bool completed = true;
        unordered_set<int> cVisited;
        for(int i = 0; i < num.size(); ++i){
            if(!visited[i] && cVisited.find(num[i]) == cVisited.end()){
                cVisited.insert(num[i]);
                auto p = path;
                p.push_back(num[i]);
                visited[i] = true;
                dfs(num, visited, ret, p);
                visited[i] = false;
                completed = false;
            }
        }
        if(completed)
            ret.push_back(path);
    }
};

 

可以看到两个dfs使用的都是引用。这样可以减少大量的赋值时间。

运行下面代码

int main(){
    vector<int> v;
    cout << "sizeof v is " << sizeof(v) << endl;
    v.push_back(4);
    cout << "sizeof v is " << sizeof(v) << endl;
    getchar();
}

可以发现输出是一样的。也就是说每个vector对象的大小都是一样的。里边保存了元素个数,指针等信息。然后通过自己的拷贝控制保证每个对象都指向不同的内存,所以

在函数调用时,调用copy constructor,开辟一片新内存,一个个赋值。应该是这个过程,所以用引用可以节约大量时间。

 

对于第二题,可以画出不去重时的搜索树,很容易就能发现,当同一层出现不同位置但是值相等的数字的时候,他们的子树是一模一样的~

所以只要保证每一层对于值相等的元素只深搜一次就可以---用hash table,也就是unordered_set。考虑去重的时候这种思路很重要~

 

更有趣的是,在计算之前将输入排序竟然可以将运行时间减少将近一半!!不知道这个是什么原因导致的。。。。可能跟unordered_set的实现有关??很奇葩的现象。

不过有一点启发就是,处理各种xxxx问题之前排个序,很多时候不仅不会增加问题处理时间,反倒会简化问题,磨刀不误砍柴工的道理吧-。-

posted on 2014-12-17 19:32  远近闻名的学渣  阅读(170)  评论(0)    收藏  举报

导航