Leetcode link: https://leetcode.com/problems/next-permutation/
解这道题需要先了解什么是“下一个 排列”的算法,否则单凭题目中给出的几个例子根本无从下手。参考这个链接:https://www.cnblogs.com/ECJTUACM-873284962/p/6390591.html
这道题要求不能使用extra memory,所以不能使用递归。下面的算法使用3次扫描解决这个问题,一共4步:
(一) 从右往左扫,找到第一个比前一个元素小的元素,其索引为p;
7 8 9 3 2 1
这里p=1
(二) 从右往左扫,找到第一个比p指向的元素大的元素,其索引为q;
7 8 9 3 2 1
这里q=2
(三) 交换 p 和 q指向的元素;
交换之前:
7 8 9 3 2 1
交换之后:
7 9 8 3 2 1
(四) 把从p+1到数组结束的所有元素倒序。
7 9 1 2 3 8
以下是C++代码和python代码,时间复杂度是O(n),空间复杂度是O(1)。
这道题还是需要一定的数学知识,面试者要能够观察出来排列的递增规律,也能看出来面试者是否聪明。本题可以用来考察面试者是否考虑问题全面,例如p和q等于0的情况。
class Solution {
public:
void nextPermutation(vector<int>& nums) {
if (nums.size()<2)
return;
int p = 0;
for (int i = nums.size() - 2; i >= 0; i--) {
if (nums[i]<nums[i + 1]) {
p = i;
break;
}
}
int q = 0;
for (int i = nums.size() - 1; i>p; i--) {
if (nums[i]> nums[p]) {
q = i;
break;
}
}
if (p == 0 && q == 0) {
reverse(nums, 0, nums.size() - 1);
return;
}
int temp = nums[p];
nums[p] = nums[q];
nums[q] = temp;
reverse(nums, p + 1, nums.size() - 1);
}
void reverse(vector<int>& nums, int left, int right) {
while (left<right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
};
class Solution:
def nextPermutation(self, nums):
if nums is None or len(nums) < 2:
return
p = 0
for index in range((len(nums) - 2), -1, -1):
if (nums[index+1] > nums[index]):
p = index
break
q = 0
for index in range((len(nums) - 1), -1, -1):
if (nums[index] > nums[p]):
q = index
break
if p == 0 and q == 0:
return self.reverseOrder( nums, 0, len(nums)-1 )
nums[p] = nums[p]^nums[q]
nums[q] = nums[p]^nums[q]
nums[p] = nums[p]^nums[q]
return self.reverseOrder( nums, p+1, len(nums)-1 )
def reverseOrder(self, nums, left, right ):
while left < right:
nums[left] = nums[left]^nums[right]
nums[right] = nums[left]^nums[right]
nums[left] = nums[left]^nums[right]
left = left + 1
right = right - 1