zoukankan      html  css  js  c++  java
  • 31. Next Permutation(中等,搞清楚啥是 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
    

    这题我看了半天都没搞懂啥是"下一个排列(next permutation)".找了些资料(http://www.geeksforgeeks.org/find-next-greater-number-set-digits/),才了解啥叫 next permutation.
    这么弄:
    假设 A = [2 1 8 7 6 5], 它的 next permutation 咋求? 这样求:

    1. 从右往左,5 6 7 8 都是增序,突然 1 降下来了, 那就所定 1;
    2. 1 右边有 8 7 6 5, 找比1大的但却是这四个数中较小的那个数, 就是 5 喽;
    3. 交换 1 和 5, 结果是 A = [2 5 8 7 6 1];
    4. 然后 对 [8 7 6 1] 增序排序. 最后返回 A = [2 5 1 6 7 8].

    打完,收功!
    这么做就能得到某序列的所谓的 next permutation 了?
    是的!
    为啥?
    没为啥,遍个程序实现它就完事了!

    题目要求中有个特殊情况,就是当 A = [4 3 2 1] 时,返回 A = [1 2 3 4].
    以上就是本题的全部解释了.
    更加详细的考虑及设置,在我的代码注释中写的很清楚.

    人家想法,自个代码:
    有个 cpp 副产品: reverse(A.begin() + start, A.end());
    这个 start 是 A = [2 1 8 7 6 5] 中元素 8 的 index, start = 2.
    (O(n)) time, (O(1)) extra space.
    严格来说,里面用到了排序,就不是(O(n)) time 了.

    // e.g.
    // A = [2 1 8 7 6 5]
    // step 1: from right to left, seek element '1';
    // step 2: from right to left, seek '5' and swap(A[1], A[5])
    //  --- After step 2, A = [2 1 8 7 6 5] --> A = [2 5 8 7 6 1]
    // step 3: reverse(A.begin() + 2, A.end())
    //  --- return A = [2 5 1 6 7 8]
    
    // special case: A = [4 3 2 1] --> will return A = [1 2 3 4]
    
    void nextPermutation(vector<int>& A) {
    	const int n = A.size();
    	if (n == 0 || n == 1)
    		return; //special case
    
    	int start;
    
    	// 4 3 2 1, can not found A[i]<A[i+1]
    	bool found = false;
    
    	// step 1
    	for (int i = n - 2; i >= 0; i--) {
    		if (A[i] < A[i + 1]) {
    			start = i + 1;
    			found = true; // found the case A[i]<A[i+1]
    			break;
    		}
    	}
    
    	// special case
    	// 4 3 2 1 --> return 1 2 3 4 directly
    	if (found == false) {
    		reverse(A.begin(), A.end());
    		return;
    	}
    
    	// step 2
    	for (int j = n - 1; j >= start; j--) {
    		if (A[j] > A[start - 1]) {
    			swap(A[j], A[start - 1]);
    			break;
    		}
    	}
    
    	// step 3
    	reverse(A.begin() + start, A.end());
    
    	return;
    }
    
  • 相关阅读:
    面试题33:把数组排成最小的数
    面试题32:从1到n整数中1出现的次数
    面试题31:连续子数组的最大和
    HTTPS 及加密信息全解析
    面试题30:最小的k个数
    linux退出vi
    linux清除当前屏幕
    java web开发环境配置
    jQuery积累
    html5离线应用详摘
  • 原文地址:https://www.cnblogs.com/ZhongliangXiang/p/7500782.html
Copyright © 2011-2022 走看看