java实现全排列(有重复)

全排列(有重复)

上一部分的全排列是无重复的,咱们遍历的条件就是想办法让每一个数字只选择一次,选择过了 ,咱们就不选,利用continue跳过,但是如果有重复数字在里面,我们恐怕就不能用数字是否重复来判断这个数字是否选择了,如果这样判断的话,我们数字会永远缺了重复的那个数字。

整体思路:

整体思路其实就是上一部分无重复的全排列思路非常像,我们开始利用的是数字不重复来选取需要的数字,那么我们现在可以通过序号是否取过,取过咱们就不要,也就是说,另外开取一个容器,来装取出数字的序号,然后判断这个序号是否取过了,如果取过了,咱们就退出

整个代码就是:

public class number{
 static ArrayList <String> w = new ArrayList();
 static List <Integer> M = Arrays.asList(1,2,3,5);
 /*多出一个容器来装数字响应的序号*/
 public static void run(ArrayList<Integer> selected,List<Integer> choose,ArrayList<Integer> to) {
  if(selected.size() == choose.size()) {
   w.add(Arrays.toString(selected.toArray()));
   return;
  }
  for(int i=0;i<choose.size();i++) {
   Integer num = choose.get(i);
   Integer a = i;//用Integer来存放i
   /*如果to里面已经有a了,那么说明这个数字已经选过,直接跳过*/
   if(to.contains(a)) {
    continue;
   }
   //与selected完全一样,to只是存储他们的序列而已
   to.add(a);
   selected.add(num);
   run(selected,choose,to);
   to.remove(a);
   selected.remove(num);
  }
 }
 public static void main(String[] args) {
  ArrayList<Integer> selected = new ArrayList();
  ArrayList<Integer> to = new ArrayList();
  run(selected,M,to);
  for(int i=0;i<w.size();i++) {
   System.out.println(w.get(i));
  }
 }
}

代码整体一看,感觉似乎差不多的代码,只是多加了一个to容器来存储数字本该有的序列而已,用了另外一种形式来挑选数字,
在这里插入图片描述
数字不同时,也是另外一种判断方式,但是数字相同时,就会发现很多组数字都重复了,因为他们是按照序列来排序的,而不是看你数字来排序的,这个时候还需要再筛选一次
在这里插入图片描述


去除重复序列


去除重复序列只需要判断一下存储字符串的容器当中,有没有存储过这一个字符串,如果存过了,就跳过去,不存进去,java自配的容器,非常好使。这串代码只需要在判断return处加上就可以了。

if(selected.size() == choose.size()) {
   if(w.contains(Arrays.toString(selected.toArray()))==false) {
    w.add(Arrays.toString(selected.toArray()));
   }
   return;
  }

在这里插入图片描述

这样就剔除了重复的字符串,但是如果想要更干净一点的代码,把两边的框框去掉,可以利用replaceAll把[ ]给换掉

最终代码:

public class number{
 static ArrayList <String> w = new ArrayList();
 static List <Integer> M = Arrays.asList(1,2,2,5);
 public static void run(ArrayList<Integer> selected,List<Integer> choose,ArrayList<Integer> to) {
  if(selected.size() == choose.size()) {
   if(w.contains(Arrays.toString(selected.toArray()).replaceAll("\\[|\\]", ""))==false) {
    w.add(Arrays.toString(selected.toArray()).replaceAll("\\[|\\]", ""));
   }
   return;
  }
  for(int i=0;i<choose.size();i++) {
   Integer num = choose.get(i);
   Integer a = i;
   if(to.contains(a)) {
    continue;
   }
   to.add(a);
   selected.add(num);
   run(selected,choose,to);
   to.remove(a);
   selected.remove(num);
  }
 }
 public static void main(String[] args) {
  ArrayList<Integer> selected = new ArrayList();
  ArrayList<Integer> to = new ArrayList();
  run(selected,M,to);
  for(int i=0;i<w.size();i++) {
   System.out.println(w.get(i));
  }
 }
}

在这里插入图片描述
很感谢提出问题的朋友,大概是参数selected出了问题,我重新修改了一下思路,利用to的序列,直接对应输出全排列即可,感兴趣的同学也可以研究一下,为啥selected会出现问题(我也挺迷惑的)

public class number{
	 static ArrayList <String> w = new ArrayList();
	 static ArrayList <String> m = new ArrayList();
	 static ArrayList <String> z = new ArrayList();

	 static List <Integer> M = Arrays.asList(1,2,2,5);
	 /*多出一个容器来装数字响应的序号*/
	 public static void run(ArrayList<Integer> selected,List<Integer> choose,ArrayList<Integer> to) {
	  /*if(selected.size() == choose.size()) {
	   w.add(Arrays.toString(selected.toArray()));
	   return;
	  }*/
	  if(to.size() == choose.size()) {//把[]去掉
		  ArrayList<Integer> temp = new ArrayList();
	   if(w.contains(Arrays.toString(to.toArray()).replaceAll("\\[|\\]", ""))==false) {
	    w.add(Arrays.toString(to.toArray()).replaceAll("\\[|\\]", ""));
	    //System.out.println(Arrays.toString(to.toArray()).replaceAll("\\[|\\]", ""));
	    //把to对应的序列转化成M中对应的符号
	    for(int i=0;i<to.size();i++) {
	    	temp.add(M.get(to.get(i)));	
	    }
	    m.add(Arrays.toString(temp.toArray()));
	   }
	  return ;
	  for(int i=0;i<choose.size();i++) {
	   Integer num = choose.get(i);
	   Integer a = i;//用Integer来存放i
	   /*如果to里面已经有a了,那么说明这个数字已经选过,直接跳过*/
	   if(to.contains(a)) {
	    continue;
	   }
	   //与selected完全一样,to只是存储他们的序列而已
	   to.add(a);
	   selected.add(num);
	   run(selected,choose,to);
	   to.remove(a);
	   selected.remove(num);
	  }
	 }
	 public static void main(String[] args) {
	  ArrayList<Integer> selected = new ArrayList();
	  ArrayList<Integer> to = new ArrayList();
	  run(selected,M,to);	 
	  for(int i=0;i<m.size();i++) {
	  //清除[]和重复序列
	  if(z.contains(m.get(i).replaceAll("\\[|\\]", ""))==false) {
		    z.add(m.get(i).replaceAll("\\[|\\]", ""));
		   }
	  }
	  for(int i=0;i<z.size();i++) {
		  System.out.println(z.get(i));
	  }
	  System.out.println(z.size());
	 }
	}

在这里插入图片描述
这样应该就没啥大问题了,有问题还可以一起讨论哇!!!
在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值