【LeetCode】Permutations & Permutations II & Next Permutations & Permutation Sequence

这篇博客详细分析了LeetCode中的四个排列问题,包括Permutations、Permutations II、Next Permutation和Permutation Sequence,探讨了它们的解题思路和代码实现,提供了C++的学习资源。

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

这里对这四个关于排列的问题进行统一分析。这四个问题有共性也有区别的。



Permutations

 

参考链接


题目描述 

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].

关键是明白其中的交换是意思

代码示例

class Solution {
public:
void get(vector<int> &num, int index, vector<vector<int > > &solution)
	{
		if(index >= num.size())
		{
			solution.push_back(num);
			return;
		}else
			for(int i = index; i < num.size(); i++)
			{
				swap(num[index],num[i]);
				get(num,index+1,solution);
				swap(num[index],num[i]);
			}
	}
	vector<vector<int > > permute(vector<int> &num) {
        // Note: The Solution object is instantiated only once.
        vector<vector<int > > solution;
		if(num.size()<1)return solution;
		get(num, 0, solution);
		return solution;
    }
};

Permutations 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].


思路:这里需要注意几个排序的地方。
除了下面代码的思路还有几个思路:
思路一:做一个结果到次数的map,在添加一个新的结果前先查找一下这个结果是否已经存在,如果存在就不添加
思路二:在交换之前判断一个准备交换的数字是否已经交换过了。

代码示例

class Solution {
public:
    void internalpermuteUnique(vector<int> &num, int index,  vector<vector<int> > &result) {
        int size = num.size();
        
        if (size == index) {
            result.push_back(num);
        }
        else {
            for (int i = index; i < size; ++i) {
                if ((i > index) && (num[i] == num[index])) 
                  continue;
                else 
                  swap(num[index], num[i]);
                internalpermuteUnique(num, index + 1, result);
            }
            sort(num.begin() + index, num.end());
        }
    }
    
    vector<vector<int> > permuteUnique(vector<int> &num) {
        vector<vector<int> > result;
        sort(num.begin(), num.end());
        internalpermuteUnique(num, 0, result);
        return result;
    }
};





Next Permutation

参考链接


题目描述 

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, do not allocate 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

思路:先从后面找到一第一个num[i] < num[i+1] 的点,然后再把第i个数据和从尾到i第一个比num[i]大的数交换位置。然后再把i后面的做一下反序就可以了。

代码示例


class Solution {
public:
    void nextPermutation(vector<int> &num) {
        int size = num.size();
        if(size < 2)	return;
        int i = 0, j = 0;         
        //找到第i个点。在i之后都是降序排列面 num[i]<num[i+1] 
		for(i = size -2;i>=0;i--)
        	if(num[i] < num[i+1])
        		break;
		if(i == -1)//说明整个数组是降序排列的,所以直接把数组反序即可
			reverse(num.begin(),num.end()); 
		else
		{//从尾向前找,找到第一个比num[i]大的数,然后和num[i]交换即可得所需序列 
			for(j = size - 1;j>i;j--)
				if(num[i] < num[j])
        			break;
 			swap(num[i],num[j]);//这个时候要从i+1到n是降序排列这时需要把后面的全部反序一下
			reverse(num.begin()+i+1,num.end()) ;
		}
    }
};



Permutation Sequence

参考链接

http://blog.youkuaiyun.com/doc_sgl/article/details/12840715

题目描述

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.


思路:

在n!个排列中,第一位的元素总是(n-1)!一组出现的,也就说如果p = k / (n-1)!,那么排列的最开始一个元素一定是nums[p]。

假设有n个元素,第K个permutation是
a1, a2, a3, .....   ..., an
那么a1是哪一个数字呢?
那么这里,我们把a1去掉,那么剩下的permutation为
a2, a3, .... .... an, 共计n-1个元素。 n-1个元素共有(n-1)!组排列,那么这里就可以知道
设变量K1 =K-1
a1 = K1 / (n-1)!
同理,a2的值可以推导为

K2 = K1 % (n-1)!
a2 = K2 / (n-2)!

 .......

K(n-1) = K(n-2) /2!
a(n-1) = K(n-1) / 1!
an = K(n-1)


下面代码中,一个关键的地方就是

for(int j = selected; j < n-i-1; j++)
                nums[j] = nums[j+1];
就是哪个数字使用过了,就从数组里去除。

代码示例

class Solution {
public:
   string getPermutation(int n, int k) {
        vector<int> nums(n);
        int pCount = 1;
        for(int i = 0 ; i < n; ++i) {
            nums[i] = i + 1;
            pCount *= (i + 1);
        }

        k--;
		string res = "";
        for(int i = 0 ; i < n; i++) {
			pCount = pCount/(n-i);
            int selected = k / pCount;
			res += ('0' + nums[selected]);
            
            for(int j = selected; j < n-i-1; j++)
                nums[j] = nums[j+1];
            k = k % pCount;
        }
        return res;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值