这是我在用回溯法写全排列的时候出现的问题,知识错误,特意对此进行巩固
首先,如果list的泛型是引用类型,那么list.add()添加的是地址,而不是值。所以,当你用一个对象(这里用list代替)来添加另一个对象(这里用list1代替),如果被添加的对象(list)值不断发生变化,那么在最后遍历list1的时候,最终的值会和list1的最后的相同
先附上一段小代码
public static void fun(){
List<List<Integer>> list= new ArrayList<>();
List<Integer> list1= new ArrayList<>();
for(int i = 1;i<=3;i++){
list1.add(i);
list.add(row);
}
//最终list的值会是[1,2,3],[1,2,3],[1,2,3]
//这里只创建了两个对象,在最后一次将row集合加入到res中时,也将前面的值进行了赋值
//list.add()加入的是指定对象的地址,当row的值进行变化时,row的内容也会发生变化
for(int i = 1;i<=3;i++){
list1.add(i);
list.add(new ArrayList<>(list1));
}
//最终list的值会是[1],[1,2],[1,2,3]
//这里是通过创建一个新的对象,将其加入到res集合中,并不会因为row的值发生变化而改变
}
这段是我在写1,2,3的全排列的时候出现的问题代码,刚开始一直用list.add(list1),导致最终的list内容都为[],因为在代码中有list1.remove(list1.size()-1);最终list1的内容为[],最后经过查阅资料,改为list.add(new ArrayList<>(list1)).
import java.util.*;
public class Main {
static List<List<Integer>> list = new ArrayList<>();
public static void main(String[] args) {
int[] nums = {1, 2, 3};
List<Integer> list1 = new ArrayList<>();
fun(nums, list1);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
public static void fun(int[] nums, List<Integer> list1) {
if (list1.size() == nums.length) {
System.out.println(list1);
list.add(new ArrayList<>(list1));
//list.add(list1);错误
//这里如果使用list.add(list1),最终会由于list1.remove(list.size()-1),list1的内容会变为0,从而使得list的内容也变为0
return;
}
for (int i = 0; i < nums.length; i++) {
if (list1.contains(nums[i])) {
continue;
}
list1.add(nums[i]);
fun(nums, list1);
list1.remove(list1.size() - 1);
}
}
}