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
Analysis:
Well, this is more like a math problem, and I don't know how to solve it.
From the wikipedia, one classic algorithm to generate next permutation is:
Step 1: Find the largest index k, such that A[k]<A[k+1]. If not exist, this is the last permutation. (in this problem just sort the vector and return.)
Step 2: Find the largest index l, such that A[l]>A[k].
Step 3: Swap A[k] and A[l].
Step 4: Reverse A[k+1] to the end.
OK! Having the algorithm then coding becomes an easy thing!
Code(C++):
class Solution { public: void nextPermutation(vector<int> &num) { // Start typing your C/C++ solution below // DO NOT write int main() function int sz = num.size(); int k=-1; int l; //step1 for (int i=0;i<sz-1;i++){ if (num[i]<num[i+1]){ k=i; } } if (k==-1){ sort(num.begin(),num.end()); return; } //step2 for (int i=k+1;i<sz;i++){ if (num[i]>num[k]){ l=i; } } //step3 int tmp = num[l]; num[l]=num[k]; num[k]=tmp; //step4 reverse(num.begin()+k+1,num.end()); } };
Code(Python):
class Solution: # @param num, a list of integer # @return a list of integer def nextPermutation(self, num): k = -1; #Step 1: find max k A[k]<A[k+1] for i in xrange(0,len(num)-1): if num[i]<num[i+1]: k = i; if k == -1: num.reverse(); return num; else: #Step 2: find l A[l]>A[k] for i in xrange(k+1, len(num)): if num[i]>num[k]: l = i; #Step 3: swap A[l] A[k] num[l], num[k] = num[k], num[l]; #Step 4: reverse k+1 to end num[k+1:len(num):1] = num[len(num)-1:k:-1]; return num;
line 16: actually no need to sort, just reverse the whole array. O(lg(n)) to O(n).
ReplyDeleteline 21: int i could start from k+1 instead of 0
ReplyDeleteThanks for your suggestion !
DeleteNice! As we need the largest indices in step 1 & 2, we can loop backward for A[k - 1] < A[k] and A[l] > A[k] and break it earlier. :)
ReplyDeleteO(n) Java Code
ReplyDeleteprivate static void reverseArray(int[] num, int index) {
for (int i = 0; i < (num.length - index) / 2; i++) {
int temp = num[i + index];
num[i + index] = num[num.length - i - 1];
num[num.length - i - 1] = temp;
}
}
public static void nextPermutation(int[] num) {
int pivot = num.length - 2;;
for (; pivot >= 0; pivot --) {
if (num[pivot] < num[pivot + 1]) break;
}
System.out.println("Pivot = " + pivot);
if (pivot == -1) {
reverseArray(num, 0);
} else {
int min_index = -1;
for (int i = pivot + 1; i < num.length; i++) {
if (num[pivot] < num[i] && (min_index == -1 || num[i] <= num[min_index])) min_index = i;
}
int temp = num[pivot];
num[pivot] = num[min_index];
num[min_index] = temp;
reverseArray(num, pivot + 1);
}
}
nice posting bro >>> makelarmp3.biz
ReplyDeleteHeyy, I made a small video for this problem using Two Pointers, you can check this out !!
ReplyDeletePlease subscribe if you find this useful:) !!
https://www.youtube.com/watch?v=WC30KHDXKB0