zoukankan      html  css  js  c++  java
  • 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]);
                }
            }
        }
    };
    
  • 相关阅读:
    vue 如何点击按钮返回上一页
    vue遍历数组和对象的方法以及他们之间的区别
    css隐藏滚动条
    DOM编程以及domReady加载的几种方式
    修改默认滚动条默认样式
    面试题集锦
    正则表达式
    闭包及应用以及顺序处理ajax请求
    实现自己的(模仿jquery)toggle函数
    Asp.Net与SEO Viewstate优化终极解决方案
  • 原文地址:https://www.cnblogs.com/tangxin-blog/p/10292325.html
Copyright © 2011-2022 走看看