leetcode 46. 全排列

Posted 阿汤的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 46. 全排列相关的知识,希望对你有一定的参考价值。

题目描述:给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:
输入: [1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]
思路:递归
假设数据规模为n(这里表示数组的长度)
  • n = 1 :只有自身一种序列
  • n = 2 :1.第一种序列就是自身 2.两数交换位置,形成第二种序列
  • n = 3:为了缩小数据规模,可以拆分成1 + 2的情况。即:[1 + 2, 3] [2 + 1, 3] [3 + 1 ,2]。每个数字都有一次机会放在首位,剩下的两个数字就变成n = 2的情况了。
  • n > 3:参考n = 3的情况,利用递归逐级缩小数据规模。
按照上述思路,翻译成C++代码如下:
/**
* @param    arr 输入的数组
* @param    start 参与排列的起始位置
* @param    end 参与排列的结束位置
*/
void Permatation(int arr[], int start, int end)
{
    // 数据规模缩小到1,直接输出
    if (start == end)
    {
        for (int i = 0; i <= end; ++i)
        {
            if (i != 0)
            {
                std::cout << " ";
            }
            std::cout << arr[i];
        }
        std::cout << std::endl;
    }
    // 数据规模缩小到2,交换位置输出两种情况
    else if (start + 1 == end)
    {
        Permatation(arr, start + 1, end);   // 输出第一种情况
        std::swap(arr[start], arr[end]);    // 交换位置
        Permatation(arr, start + 1, end);   // 输出第二种情况
        std::swap(arr[start], arr[end]);    // 复原交换,保证不影响后续操作
    }
    // 数据规模大于2
    else
    {
        Permatation(arr, start + 1, end);       // 首位数字不变,缩小规模
        for (int i = start + 1; i <= end; ++i)
        {
            std::swap(arr[start], arr[i]);      // 从start + 1开始,每个数字都有一次机会放在首位
            Permatation(arr, start + 1, end);   // 缩小规模
            std::swap(arr[start], arr[i]);      // 复原本次交换,保证不影响后续操作
        }
    }
}

int main()
{
    int arr[] = { 1, 2, 3};
    Permatation(arr, 0, sizeof(arr) / sizeof(arr[0]) - 1);
    std::cin.get();
    return 0;
}

输出:

1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
经过分析,n = 2 和 n > 2 时候的处理过程十分相似,可以合并在一起。
AC代码,执行用时:8 ms
class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> ret;
        gen_perm(nums, 0, nums.size() - 1, ret);
        return ret;
    }
    void gen_perm(vector<int>& nums, int start, int end, vector<vector<int>> & ret)
    {
        if(start == end)
        {
            ret.push_back(nums);
        }
        else
        {
            for(int i = start; i <= end; ++i)
            {
                swap(nums[start], nums[i]);
                gen_perm(nums, start + 1, end, ret);
                swap(nums[start], nums[i]);
            }
        }
    }
};

以上是关于leetcode 46. 全排列的主要内容,如果未能解决你的问题,请参考以下文章

[Leetcode 46]全排列 Permutations 递归

LeetCode 46. 全排列(Permutations)

LeetCode:全排列46

LeetCode:46. 全排列47. 全排列 II

LeetCode46 回溯算法求全排列,这次是真全排列

[LeetCode] 46. Permutations(全排列)