#31 Next Permutation———Top 100 Liked Questions

本文深入解析字典序排列算法,通过实例演示如何找出给定数字序列的下一个更大的排列,若不存在则重新排序至最小状态。文章详细阐述了算法步骤,包括查找左小右大的数对、交换并部分排序,最终实现就地修改,不使用额外内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place and use only constant extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

"""

第一次:字典序算法。在提交过程中,1)当nums是降序排列时,直接将倒序的nums返回,第一次写的return语句,出错,第二次直接nums = sorted(nums),结果也是错的,后又改成nums.sort(),就可以了。题目要求就地改变in-place!因此不能写return语句,这样需要设置flag位,以保只需要找第一个左边小于右边值的i。

区别:sorted(iterable,key=None,reverse=False,返回新的列表,对所有可迭代的对象均有效

            sort(key=None,reverse=False) 就地改变列表  reverse:True反序;False 正序

 

"""

class Solution(object):
    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        flag = 0
        for i in range(len(nums) - 2, -1, -1):
            if nums[i] < nums[i + 1]:
                for j in range(len(nums) - 1, -1, -1):
                    if nums[j] > nums[i]:
                        nums[i], nums[j] = nums[j], nums[i]
                        nums[i + 1:] = sorted(nums[i + 1:])
                        flag = 1
                        break
            if flag:
                break
        if not flag:
            nums.sort()                                #1)

"""

Runtime: 24 ms, faster than 99.74% of Python online submissions for Next Permutation.

Memory Usage: 11.9 MB, less than 5.74% of Python online submissions for Next Permutation.

"""

 字典序算法:

①字典序示例:123, 132, 213, 231, 312, 321

②字典序算法:如果当前排列时124653,找它的下一个排列的方法如下:从右到左遍历,找到第一个左邻小于右邻的数,如果找不到, 说明排列求解完成,否则没完成。在124653中找到46,记录4的位置i,然后再从右到左遍历,找到第一个大于4的数,这是是5,记录5的位置为j,将4和5交换,此时排列为125643,最后对于i位置之后的数即643进行升序排列,即346,得到的125346是124653的下一个字典序。

参考:字典序算法

在 C++ 中,标准库并没有直接提供名为 `<permutation>` 的头文件。如果你需要处理排列(permutation)相关的操作,可以使用以下方法: ### 1. **使用 `<algorithm>` 中的 `std::next_permutation` 或 `std::prev_permutation`** - 这两个函数可以生成序列的全排列或判断是否可以生成下一个排列。 - 示例: ```cpp #include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 3}; do { for (int x : v) std::cout << x << " "; std::cout << "\n"; } while (std::next_permutation(v.begin(), v.end())); return 0; } ``` - 输出: ``` 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 ``` ### 2. **使用 `<numeric>` 中的 `std::iota` 初始化序列** - 如果你需要生成一个连续的整数序列,可以使用 `std::iota`。 - 示例: ```cpp #include <numeric> #include <vector> #include <iostream> int main() { std::vector<int> v(5); std::iota(v.begin(), v.end(), 1); // 填充 1, 2, 3, 4, 5 for (int x : v) std::cout << x << " "; return 0; } ``` ### 3. **手动实现排列生成** - 如果你需要更复杂的排列操作,可以手动实现递归或回溯算法。 - 示例(递归生成排列): ```cpp #include <vector> #include <iostream> void permute(std::vector<int>& nums, int start, std::vector<std::vector<int>>& result) { if (start == nums.size()) { result.push_back(nums); return; } for (int i = start; i < nums.size(); i++) { std::swap(nums[start], nums[i]); permute(nums, start + 1, result); std::swap(nums[start], nums[i]); // 回溯 } } int main() { std::vector<int> nums = {1, 2, 3}; std::vector<std::vector<int>> result; permute(nums, 0, result); for (const auto& perm : result) { for (int x : perm) std::cout << x << " "; std::cout << "\n"; } return 0; } ``` ### 4. **使用第三方库** - 如果你需要更高级的组合数学功能,可以考虑使用第三方库如: - **Boost.Combinatorics**(提供排列、组合等操作) - **C++ Combinatorics Library**(如 `cpp-permute`) ### 常见问题 1. **为什么没有 `<permutation>` 头文件?** - C++ 标准库没有直接提供 `<permutation>`,但 `<algorithm>` 中的 `std::next_permutation` 和 `std::prev_permutation` 可以满足基本需求。 2. **如何生成所有排列?** - 使用 `std::next_permutation` 或递归回溯方法。 3. **如何优化排列生成的性能?** - 对于大规模数据,可以考虑 Heap&#39;s algorithm(非递归实现)或并行计算。 4. **如何处理重复元素的排列?** - 使用 `std::sort` 排序后,跳过重复元素(在 `std::next_permutation` 之前检查)。 5. **是否有现成的库支持排列?** - Boost 和某些第三方库提供更高级的组合数学功能。 ### 示例代码(使用 `std::next_permutation` 生成排列) ```cpp #include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 2}; std::sort(v.begin(), v.end()); // 排序以跳过重复排列 do { for (int x : v) std::cout << x << " "; std::cout << "\n"; } while (std::next_permutation(v.begin(), v.end())); return 0; } ``` ### 输出: ``` 1 2 2 2 1 2 2 2 1 ``` 如果你有更具体的需求(如部分排列、排列索引计算等),可以进一步说明!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值