• 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;
    }
    
  • 相关阅读:
    一、单一职责原则
    四、接口隔离原则
    彼得·林奇的25条黄金规则
    程序员的四个境界
    VS2008开发.NET 2.0的项目时,可用的C#3.0语言特性一览表
    Linq试用问题总结
    SQL Server 2000中修改数据库COLLATE一例
    SQL Tip:将SP生成的结果集Insert到另一Table中
    OOAD读书笔记(一):什么是好的软件?
    成功创业的8个关键点
  • 原文地址:https://www.cnblogs.com/ZhongliangXiang/p/7500782.html
Copyright © 2020-2023  润新知