非递归全排序(非字典算法)(新增,可处理重复数)

非c++ next_permutation方式
数组不可有重复值
时间复杂度 n^2 ✖ n! 好大!
思路:
nums = [1,2,3, 4]
先建立空lists 数量为n! = 4! = 24
[
[],
[],
[],
.
.
.
]
sPtr = 0
[1, 2, 3, 4]
3!=6次插入nums[sPtr]后,指针sPtr后移(超出回归0)
[
[1], // sPtr = 0
[1],
[1],
[1],
[1],
[1],
[2], // sPtr = 1



]

[1, 2, 3, 4]
插入前检测nums[sPtr] 是否已存在当前list中,是则指针sPtr后移(超出回归0)
2!=2次插入nums[sPtr]后,指针sPtr后移(超出回归0)
[
[
[1],[2] // sPtr = 1
[1],[2]
[1],[3] // sPtr = 2
[1],[3]
[1],[4] // sPtr = 3
[1],[4]
… // sPtr = 0


]

[1, 2, 3, 4]
插入前检测nums[sPtr] 是否已存在当前list中,是则指针sPtr后移(超出回归0)
1!=1次插入nums[sPtr]后,指针sPtr后移(超出回归0)
[
[1],[2],[3]
[1],[2],[4]
[1],[3],[2]
[1],[3],[4]
[1],[4],[2]
[1],[4],[3]



]

[1, 2, 3, 4]
插入前检测nums[sPtr] 是否已存在当前list中,是则指针sPtr后移(超出回归0)
0!=1次插入nums[sPtr]后,指针sPtr后移(超出回归0)
[
[1],[2],[3],[4]
[1],[2],[4],[3]
[1],[3],[2],[4]
[1],[3],[4],[2]
[1],[4],[2],[3]
[1],[4],[3],[2]



]

/*
 * authur: Zefang Yu
 * lastUpdate: 12:02 5/2/20
 */
public class Solution {
    /*
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    public List<List<Integer>> permute(int[] nums) {
        // write your code here
        int len = nums.length; 
        int totalList = factorial(len);//总排列数量
        
        List<List<Integer>> lists = new ArrayList<List<Integer>>();
		// 在lists中建立空list
        for(int i = 0; i < totalList; i++){
            lists.add(new ArrayList<Integer>());
        }
        
        int sPtr = 0;// nums的指针index
        
        //从所有排序的第一位开始排序,->第二位->..->最后一位
        for(int i = 0; i < len; i++){
            
            int factor = factorial(len-i-1);//当前位数在所有排列中出现的次数
            
            //第一个list到最后一个list
            for(int j = 0; j < totalList; j++){
            	
            	//用完nums[sPtr]所有次数后,sPtr指针后移
                if( j != 0 && (j%factor == 0)){
                    sPtr = (sPtr+1)%len;
                }
                
                //向所有空list(排列第一位时)中输入第一个数值时跳过判断
                if(i != 0){
                	
                	//判断当前list是否包含指针所指数值,包含则指针后移
                    while(lists.get(j).contains(nums[sPtr])){
                        sPtr = (sPtr+1)%len;
                    }
                }
                lists.get(j).add(nums[sPtr]);// 向当前list输入数值
            }
        }
        System.out.println(lists);
        
        return lists;
        
    }
    
    // return n!
    public int factorial(int n){
        int res = 1;
        for(int i = 1; i <= n; i++){
            res *= i; 
        }
        return res;
    }
    
}

改进思路:(可处理重复数)
基础思路同上,为处理重复数,加入时不加入数,而改为加入指针。
nums = [1,2,3, 4]
先建立空lists 数量为n! = 4! = 24
[
[],
[],
[],
.
.
.
]
sPtr = 0
[1, 2, 3, 4]
3!=6次插入sPtr后,指针sPtr后移(超出回归0)
[
0, // sPtr = 0
0,
0,r
0,
0,
0,
1, // sPtr = 1



]

[1, 2, 3, 4]
插入前检测sPtr 是否已存在当前list中,是则指针sPtr后移(超出回归0)
2!=2次插入sPtr后,指针sPtr后移(超出回归0)
[
[
0,1 // sPtr = 1
0,1
0,2 // sPtr = 2
0,2
0,3 // sPtr = 3
0,4
… // sPtr = 0


]


[1, 2, 3, 4]
插入前检测sPtr 是否已存在当前list中,是则指针sPtr后移(超出回归0)
0!=1次插入sPtr后,指针sPtr后移(超出回归0)
[
0,1,2,3
0,1,3,2
0,2,1,3
0,2,3,1
0,3,1,2
0,4,2,1



]

完成后使用循环将指针转换为实际数值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值