算法<含相同元素数组的全排列>

可以借鉴我的上一篇博客(http://blog.csdn.net/gpwner/article/details/75212890)来简单得得到答案:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author
 * @version 2017/7/5.19:28
 */
public class Demo {
    public static void main(String[] args) {
        int[] nums = {1, 2, 1};
        List<List<Integer>> result = new Demo().permuteUnique(nums);
        for (List<Integer> integers : result) {
            for (Integer integer : integers) {
                System.out.print(integer + " ");
            }
            System.out.println();
        }
    }

    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        helper(res, nums, 0);
        return res;
    }

    private  void helper(List<List<Integer>> res, int[] nums, int start) {
        if (start == nums.length - 1) {
            //将int[]转换为List
            List<Integer> temp = IntStream.of(nums).boxed().collect(Collectors.toList());
            res.add(temp);
            return;
        }
        for (int i = start; i < nums.length; ++i) {
            if (isDuplicate(nums, start, i))
                continue;
            swap(nums, start, i);
            helper(res, nums, start + 1);
            swap(nums, start, i);
        }
    }

    private  void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }

    private  boolean isDuplicate(int[] nums, int i, int j) {
        //注意这里一定是小于,不能是小于等于
        while (i < j) {
            if (nums[i] == nums[j])
                return true;
            i++;
        }
        return false;
    }
}

这种办法效率比较低,因为每一次 都要比较,很耗时间

新办法:

在做全排列之前,首先统计出每一个元素的个数,将数组1,1,2的元素进行统计,得到item={1,2},count={2,1}表示在待全排序的数组中元素1的个数为2,元素2的个数为1。然后再进行全排列的时候遍历item数组,level表示排列好的数组元素的下标,level=0表示第一个元素,level=1表示第二个元素,level=2表示第三个元素,,,,,,,每一次取出一个元素的时候,count对应的位置就减一,做好这种排列之后再加回来。
用代码表示就是:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author
 * @version 2017/7/5.19:28
 */
public class PermuteUnique {
    public static void main(String[] args) {
        int[] nums = {1, 2, 1};
        List<List<Integer>> result = new PermuteUnique().permuteUnique(nums);
        for (List<Integer> integers : result) {
            for (Integer integer : integers) {
                System.out.print(integer + " ");
            }
            System.out.println();
        }
    }

    public List<List<Integer>> permuteUnique(int[] nums) {
        Map<Integer, Integer> frequencies = new HashMap<>();
        for (int i : nums) {
            if (frequencies.containsKey(i)) {
                int val = frequencies.get(i);
                val++;
                frequencies.put(i, val);
            } else {
                frequencies.put(i, 1);
            }
        }
        //元素
        int[] items = new int[frequencies.size()];
        //元素对应的个数
        int[] count = new int[frequencies.size()];
        int index = 0;
        for (Map.Entry<Integer, Integer> entry : frequencies.entrySet()) {
            items[index] = entry.getKey();
            count[index] = entry.getValue();
            index++;
        }
        List<List<Integer>> result = new ArrayList<>();
        //排列组合得到的数组,长度等于原来的数组
        int[] permutation = new int[nums.length];
        backtrack(items, count, permutation, result, 0);
        return result;
    }


    //level 表示排列组合得到的数组的第几个位置,level=0表示第一个元素,level=1表示第二个元素,level=2表示第三个元素
    private void backtrack(int[] items, int[] count, int[] permutation, List<List<Integer>> result, int level) {
        if (level == permutation.length) {
            List<Integer> validPermutation = IntStream.of(permutation).boxed().collect(Collectors.toList());
            result.add(validPermutation);
        }
        for (int j = 0; j < items.length; j++) {
            if (count[j] == 0)
                continue;
            permutation[level] = items[j];
            count[j]--;
            backtrack(items, count, permutation, result, level + 1);
            count[j]++;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值