处理重复元素的数组的全排列(java实现)

题目描述:将一个数组全排列后输出。

eg1:{“a”,“b”,“c”} ——>[a, b, c]、[a, c, b]、[b, a, c]、[b, c, a]、[c, a, b]、[c, b, a]

eg2:{"a", "c", "c", "d",} ——> 如下所示:

                                                    [a, c, c, d]
                                                    [a, c, d, c]
                                                    [a, d, c, c]
                                                    [c, c, a, d]
                                                    [c, c, d, a]
                                                    [c, a, c, d]
                                                    [c, a, d, c]
                                                    [c, d, a, c]
                                                    [c, d, c, a]
                                                    [d, c, c, a]
                                                    [d, c, a, c]
                                                    [d, a, c, c]

说明:当数组中有元素重复的时候,需要将排序后重复的数组给去除。


前言:关于数组的全排列网上的教程很多,可是大部分都没有处理重复元素的问题,这里我将我的思路及实现分享出来,望多多指教。

分析:当我们实现数组的全排列时,我们

                        1、将第一个元素和最后一个元素做交换,就可以得到一种数组排列。

                        2、将第二个元素和最后一个元素做交换,就可以得到一种数组排列。

                        …………………………

                        n、将第n个元素和最后一个元素做交换,即可得到一种数组排列。

扫描二维码关注公众号,回复: 154877 查看本文章

通过以上分析,我们可以使用递归的思想来进行全排列,递归出口为:当 n==array.length 时递归结束。

方案一:

1、FullArangement类:核心类,主要实现数组的全排列等功能。

package stu.kx.test1_FullArrangement;

import java.util.Arrays;

/**
 * 
 * @author 康茜
 *全排列:
 *将数组中的元素全排列(不能去除重复的元素)
 *
 *需要去除重复的元素;既然元素值是重复的,那么我们可以将问题简化,将问题分解成去除数组中重复元素和全排列数组两部分;
 */
public class FullArrangement {
    
    public static void doFullArrangement(String[] array) {
        getAllOrder(array, 0, array.length);
    }
    
    /**
     * 
     * @param start 从start开始,到end结束来全排列数组
     * @param end
     */
    private static void getAllOrder(Object[] array, int start, int end) {
        if(start == end) {
            System.out.println(Arrays.toString(array));//使用Arrays工具类遍历输出数组元素
        } else {
            for(int i = start; i < end; i++) {
                swap(array, start, i);
                getAllOrder(array, start + 1, end);
                swap(array, i, start);
            }
        }
    }
    
    //数组中的两个元素交换位置
    private static void swap(Object[] array, int i, int j) {
        if(i == j) {
            return;
        }
        Object temp = array[i];
        array[i] = array[j];
        array[j] = temp;
        
    }
}

2、测试类:

package stu.kx.test1_FullArrangement;

public class Test {
	public static void main(String[] args) {
		String[] array = {"a","c","c","d"};
		FullArrangement.doFullArrangement(array);
	}
}

3、测试结果:


从以上输出结果来看,如果数组中含有重复的元素,则输出结果中会有重复的输出结果,可是我们所预期的结果并不是这样,那么我们来看看方案二。


方案二:

思路:在原先的解题思路上,增加了一个静态list<String> 该list中存储着本次全排列每次输出的数组排列的字符串形式,在每次输出之前判断该list中是否包含该数组的字符串形式,来判断结果是否重复,若重复,则不进行输出,否则,则输出。

1、FullArrangement类(核心类):处理全排列问题及结果重复问题。

package stu.kx.test1_FullArrangement;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 
 * @author 康茜
 *全排列(去除重复排序数组的全排序):——全排列的java实现(无重复元素)
 *
 *需要去除重复的元素;既然元素值是重复的,那么我们可以将问题简化,将问题分解成去除数组中重复元素和全排列数组两部分;
 */
public class FullArrangement1 {
	private static List<String> list = new ArrayList<>();
	
	public static void doFullArrangement(String[] array) {
		/*
		 * 清空list,因为此list是静态的,因此每次排序时都需要清空,否则的话若重复调用排序的方法的话将不会去除重复的排序
		 */
		list.removeAll(list);
		getAllOrder(array, 0, array.length);
	}
	
	/**
	 * 
	 * @param start 从start开始,到end结束来全排列数组
	 * @param end
	 */
	private static void getAllOrder(Object[] array, int start, int end) {
		if(start == end) {
			//将数组转换成字符串,通过判断list中是否包含该字符串(数组的字符串形式) 来 判断该数组有没有被输出过,从而
			//去除重复的数组排序。
			String arrayStr = Arrays.toString(array);
			if(!list.contains(arrayStr)) {
				list.add(arrayStr);
			} else {
				System.out.println(arrayStr);
			}
			return;
			//System.out.println(Arrays.toString(array));//使用Arrays工具类遍历输出数组元素
		} else {
			for(int i = start; i < end; i++) {
				swap(array, start, i);
				getAllOrder(array, start + 1, end);
				swap(array, i, start);
			}
		}
	}
	
	//数组中的两个元素交换位置
	private static void swap(Object[] array, int i, int j) {
		if(i == j) {
			return;
		}
		Object temp = array[i];
		array[i] = array[j];
		array[j] = temp;
		
	}
}

2、测试类。

package stu.kx.test1_FullArrangement;

public class Test {

	public static void main(String[] args) {
		String[] array = {"a","c","c","d"};
		FullArrangement1.doFullArrangement(array);
	}

}

3、测试结果。



结果:从测试结果可以看出,全排列的结果不存在重复的结果。







猜你喜欢

转载自blog.csdn.net/kangxidagege/article/details/79618956