【hot100】046全排列
一、思路
回溯的入门题,核心思路就是递归(基础位置)嵌套循环(被交换的数字),然后每个循环都会将之前的交换操作取消,所以称为回溯。至于全排列这里利用交换的思想就是每个数字都与其身后的数字交换一次,即可得到全部排列。
二、记忆
1.java中复杂数据类型传递的都是引用,所以并不能直接赋值,不然最后指向的都是同一个output,一定要新初始化一个List然后把output的值传进去
if (first==n){
res.add(new ArrayList<Integer>(output));//到底后将output列表加入res列表
}
2. java中的8种基本数据类型,其余皆为复杂类型或者包装类
一、Java中的8种基本数据类型(Primitive Types)
类型(Type) 占用字节(Bytes) 位数(Bits) 默认值(Default Value) 取值范围(Range) 说明(说明/用途) byte 1 字节 8 位 0 -128 ~ 127 整数,节省内存,适用于大型数组 short 2 字节 16 位 0 -32,768 ~ 32,767 较小的整数值,节省内存 int 4 字节 32 位 0 -2^31 ~ 2^31-1 默认整数类型,最常用 long 8 字节 64 位 0L -2^63 ~ 2^63-1 大整数值,后缀 L float 4 字节 32 位 0.0f 大约 ±3.40282347E+38F(6-7 位小数) 单精度浮点数,后缀 f 或 F double 8 字节 64 位 0.0d 大约 ±1.79769313486231570E+308(15位小数) 双精度浮点数,默认浮点类型 char 2 字节 16 位 '\u0000' 0 ~ 65535(Unicode字符) 存储单个字符 boolean 1 位(虚拟机优化) 不固定 false true 或 false 逻辑类型
✅ 二、注意事项
1. 默认值问题
- 基本类型的默认值适用于 成员变量。
- 局部变量(函数内部定义的变量)没有默认值,必须显式初始化,否则编译报错。
2. 整数默认类型
- 整数 默认是
int
类型:
int a = 100; // 正确 long b = 100; // 正确,自动提升 long c = 100L; // 正确,明确 long
3. 浮点数默认类型
- 浮点数 默认是
double
类型:
float x = 3.14f; // 必须加 f double y = 3.14; // 正确
4. char 是无符号的
char
用于表示 Unicode 字符,实际上是 0~65535 范围的整数:
char ch = 'A'; // 存储字符 char ch2 = 65; // 也是合法,代表 'A'
5. boolean 只有 true / false
boolean flag = true; boolean isEmpty = false;
✅ 三、基本类型与包装类(Wrapper Classes)
基本数据类型(Primitive Type) 包装类(Wrapper Class) byte Byte short Short int Integer long Long float Float double Double char Character boolean Boolean
- 包装类存在于
java.lang
包中,用于 集合框架(如 List、Map)、泛型等不能直接存储基本类型的地方。- 自动装箱(Autoboxing):基本类型自动转换为包装类。
- 自动拆箱(Unboxing):包装类自动转换为基本类型。
int num = 10; Integer numObj = num; // 自动装箱 int value = numObj; // 自动拆箱
✅ 四、扩展:默认值示例
public class Test { static int a; static boolean b; static char c; static double d; public static void main(String[] args) { System.out.println(a); // 0 System.out.println(b); // false System.out.println((int)c); // 0 System.out.println(d); // 0.0 } }
🎉 总结:
- Java 基本数据类型共 8 种,分为整数、浮点数、字符、布尔类型。
- 子类化包装类提供了对象形式,方便在泛型和集合中使用。
- 顺序记忆口诀(整型从小到大,浮点数,字符,布尔):
byte < short < int < long < float < double < char < boolean
3.Collections的常用方法
一、排序与搜索
1.
sort(List<T> list)
用途:对列表按自然顺序(升序)排序。
要求:列表元素必须实现
Comparable
接口。示例:
java
复制
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4)); Collections.sort(list); // [1, 3, 4]2.
sort(List<T> list, Comparator<? super T> c)
用途:通过自定义比较器排序。
示例(降序排序):
java
复制
Collections.sort(list, (a, b) -> b - a); // [4, 3, 1]3.
binarySearch(List<? extends Comparable<? super T>> list, T key)
用途:在已排序的列表中二分查找元素。
返回值:找到返回索引,否则返回负数。
示例:
java
复制
int index = Collections.binarySearch(list, 3); // 1
二、集合操作
4.
reverse(List<?> list)
用途:反转列表元素的顺序。
java
复制
Collections.reverse(list); // [4, 1, 3](原列表被修改)5.
shuffle(List<?> list)
用途:随机打乱列表顺序。
java
复制
Collections.shuffle(list); // 如 [1, 4, 3]6.
swap(List<?> list, int i, int j)
交换 List 中的两个元素。
Collections.swap(list, 0, 2); System.out.println(list); // 根据原顺序改变
7.
fill(List<? super T> list, T obj)
用途:用指定对象填充列表的所有元素。
java
复制
Collections.fill(list, 0); // [0, 0, 0]8.
copy(List<? super T> dest, List<? extends T> src)
用途:将源列表内容复制到目标列表(需保证目标列表长度足够)。
java
复制
List<Integer> dest = new ArrayList<>(Arrays.asList(0, 0, 0)); Collections.copy(dest, list); // dest 变为 [3, 1, 4]9.
replaceAll(List<T> list, T oldVal, T newVal)
用途:替换列表中所有匹配的旧值。
java
复制
Collections.replaceAll(list, 3, 5); // [5, 1, 4]
三、极值与频率
10.
max(Collection<? extends T> coll)
/min(...)
用途:根据自然顺序查找最大/最小值。
java
复制
int max = Collections.max(list); // 411.
frequency(Collection<?> c, Object o)
用途:统计元素在集合中的出现次数。
java
复制
int count = Collections.frequency(list, 3); // 112.
disjoint(Collection<?> c1, Collection<?> c2)
用途:判断两个集合是否没有交集。
java
复制
boolean noCommon = Collections.disjoint(list1, list2);
四、其他工具方法
13.
addAll(Collection<? super T> c, T... elements)
用途:批量添加元素到集合。
java
复制
Collections.addAll(list, 5, 6, 7); // 添加 5,6,714.
checkedCollection(Collection<E> c, Class<E> type)
用途:创建类型安全的集合(运行时检查元素类型)。
java
复制
List<String> checkedList = Collections.checkedList(new ArrayList<>(), String.class); checkedList.add(100); // 抛出 ClassCastException15.
rotate(List<?> list, int distance)
用途:旋转列表元素(如右移2位:
[1,2,3,4]
→[3,4,1,2]
)。java
复制
Collections.rotate(list, 2);
三、代码
public List<List<Integer>> permute(int[] nums){
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
List<Integer> output = new ArrayList<>();
for (int i = 0;i<n;i++){//初始化output列表,用于后续交换
output.add(nums[i]);
}
backtrack(n,output,res,0);
return res;
}
private void backtrack(int n,List<Integer> output,List<List<Integer>> res,int first){
if (first==n){
res.add(new ArrayList<Integer>(output));//到底后将output列表加入res列表
}
for (int i =first;i<n;i++){
Collections.swap(output,first,i);//从first开始,逐个向后交换;
backtrack(n,output,res,first+1);//后一位全排列
Collections.swap(output,first,i);//还原这一层的output
}
}