写在前面:这题和全排列不含重复元素的那题几乎一样,我比较垃圾,就用HashSet去掉了重复的元素但是看了九章算法的答案也没看懂,他写的很有感觉。
用了hash,本来想着怎么写hashcode()和equal()方法的,哪知道都帮我写好了,Integer类型的元素存储在List中的hashcode()和equal()的方法可以直接使用
下面是源代码和我的测试代码:
//这是ArrayList父类public abstract class AbstractList<E>中的源码
public int hashCode() {int hashCode = 1;for (E e : this)hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());return hashCode;}public boolean equals(Object o) {if (o == this)return true;if (!(o instanceof List))return false;ListIterator<E> e1 = listIterator();ListIterator<?> e2 = ((List<?>) o).listIterator();while (e1.hasNext() && e2.hasNext()) {E o1 = e1.next();Object o2 = e2.next();if (!(o1==null ? o2==null : o1.equals(o2)))return false;}return !(e1.hasNext() || e2.hasNext());}
@Testpublic void test() {List<Integer> list1 = new ArrayList<>();list1.add(1);List<Integer> list2 = new ArrayList<>();list2.add(2);List<Integer> list3 = new ArrayList<>();list3.add(1);System.out.println(list1.hashCode());System.out.println(list2.hashCode());System.out.println(list3.hashCode());System.out.println(list1==list2);System.out.println(list1==list3);System.out.println(list2==list3);System.out.println(list1.equals(list2));System.out.println(list1.equals(list3));System.out.println(list2.equals(list3));}
//运行结果
// 32
// 33
// 32
// false
// false
// false
// false
// true
// false
下面是我写的代码,只是使用HashSet去重
import org.junit.Test;import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;public class permuteUnique {/*** @param : A list of integers* @return: A list of unique permutations* <p>* 16. 带重复元素的排列* 给出一个具有重复数字的列表,找出列表所有不同的排列。* <p>* 样例* 给出列表 [1,2,2],不同的排列有:* <p>* [* [1,2,2],* [2,1,2],* [2,2,1]* ]* 挑战* 使用递归和非递归分别完成该题。* <p>* 写过不含重复元素的全排列,这提是含重复元素的,应该相差不大*/public List<List<Integer>> permuteUnique(int[] nums) {// write your code hereHashSet<List<Integer>> hashResult = new HashSet<>();List<List<Integer>> result = new ArrayList<>();List<Integer> list = new ArrayList<>();if (nums == null) {return result;}if (nums.length == 0) {result.add(list);return result;}boolean[] color = new boolean[nums.length];for (int i = 0; i < nums.length; i++) {color[i] = false;}dfs(hashResult, list, nums, color);result = new ArrayList<>(hashResult);return result;}public void dfs(HashSet<List<Integer>> hashResult, List<Integer> list, int[] nums, boolean[] color) {if (list.size() == nums.length) {hashResult.add(new ArrayList<>(list));return;}for (int i = 0; i < nums.length; i++) {if (color[i] == false) {list.add(nums[i]);color[i] = true;dfs(hashResult, list, nums, color);color[i] = false;list.remove(list.size() - 1);}}}@Testpublic void testPermuteUnique() {
// List<List<Integer>> result = permuteUnique(new int[]{1, 2, 2});
// for (int i = 0; i < result.size(); i++) {
// System.out.println(result.get(i).toString());
// }}
}
下面是九章的答案,写的很难懂,狠巧妙
和没有重复元素的 Permutation 一题相比,只加了两句话:
Arrays.sort(nums) // 排序这样所有重复的数
if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) { continue; } // 跳过会造成重复的情况
public List<List<Integer>> permuteUnique(int[] nums) {List<List<Integer>> results = new ArrayList<>();if (nums == null) {return results;}Arrays.sort(nums);dfs(nums, new boolean[nums.length], new ArrayList<Integer>(), results);return results;}private void dfs(int[] nums,boolean[] visited,List<Integer> permutation,List<List<Integer>> results) {if (nums.length == permutation.size()) {results.add(new ArrayList<Integer>(permutation));return;}for (int i = 0; i < nums.length; i++) {if (visited[i]) {continue;}if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {continue;}permutation.add(nums[i]);visited[i] = true;dfs(nums, visited, permutation, results);visited[i] = false;permutation.remove(permutation.size() - 1);}}