leetcode 47. Permutations II

全排列数组

为了得到最快的速度和最小的空间;先计算结果需要容纳多大的数组;

复制代码
    int GetCMN(int m, int n) {
        if (n == m || n == 0)
            return 1;
        int mm = 1;
        n = m -n > n?n:m-n;
        for (int i = 1; i <= n; ++i) {
            mm *= m;
            --m;
        }
        int nn = 1;
        while (n > 0) {
            nn *= n;
            --n;
        }
        return mm / nn;
    }
    int GetCount(vector<int>& nums) {
        int count = 1;
        for (int i = 0; i < nums.size(); ++i) {
            int n = 1;
            int m = nums.size() - i;
            while (i + 1 < nums.size() && nums[i] == nums[i + 1]) {
                ++i;
                ++n;
            }
            count *= GetCMN(m, n);
        }
        return count;
    }
View Code
复制代码

获取该数组的全排列

复制代码
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> result;
        if (nums.size() == 0)
            return result;
        sort(nums.begin(), nums.end());
        //cout << GetCount(nums) << endl;
        nums.reserve(GetCount(nums));
        do {
            result.push_back(nums);
        } while (next_permutation(nums.begin(), nums.end()));
        return result;
    }
复制代码

这里用到了stl里面的next_permutation函数;该意思是下一个排列组合方式;其实是找到下一个比当前序列大的数组,比如:{1,1,2,2,3,3,3}下一个比当前大的:{1,1,2,3,2,3,3};

通过查看该源码可以发现,具体的实现方式;大致如下所示

复制代码
    bool __next_permutation(vector<int>::iterator first, vector<int>::iterator last) {
        auto i = last;
        if (first == last || first == --i)
            return false;
        while (true) {
            auto p = i;
            if (*--i < *p) {
                auto j = last;
                while (*i >= *--j);
                swap(*i, *j);
                reverse(p, last);
                return true;
            }
            if (i == first) {
                reverse(first, last);
                return false;
            }
        }
    }
复制代码

1、从右往左遍历到第一个比自己小的数字;本身位置记为p,它左边位置记为i;

2、寻找要跟i调换位置数字;从右往左找到第一个比*i 大的位置记为j;

3、将i和j的值互换;这样从右往左到达p依旧是递增的序列;

4、将p到结尾的数组进行翻转,则产生了全新的从小到大排列的数组;则可以进行下一轮全新的排列;

 

posted @   LCAC  阅读(145)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示