java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 |
---|
1. 暴力回溯
解题思路:时间复杂度O( n n n^n nn),但是严格来说只到了O( n ∗ n ! n*n! n∗n!) 因为很多元素只进行了一个判断,没有执行其它操作,所以它们不会很耗费时间,如果把判断算上,则是n^n时间复杂度。空间复杂度O(n) |
---|
- 创建一个flag数组,boolean类型。标志当前数字是否被选过。
- 我们每个位置的数字枚举时,都先检查flag数组,如果当前数字为false,则可选。
- 直到所有数字枚举完成
class Solution {int[] nums;boolean[] numsFlag;int len;List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> permute(int[] nums) {this.nums = nums;this.len = nums.length;this.numsFlag = new boolean[len];ArrayList<Integer> records = new ArrayList<>();backTracking(records);return ans;}public void backTracking(List<Integer> records){if(records.size() == len) ans.add(new ArrayList<>(records));else{for(int i = 0;i<len;i++){if(this.numsFlag[i]==false){this.numsFlag[i] = true;records.add(nums[i]);backTracking(records);this.numsFlag[i] = false;records.remove(records.size()-1);}}}}
}
2. 分区法+回溯
解题思路:时间复杂度O( n ∗ n ! n*n! n∗n!),空间复杂度O(n) |
---|
- 将数组分为两个区域,用index下标分割,index左边保存当前已经选择的数字,右边保存剩余可选的数字
- 每次通过交换操作,将我们想要在这次选择的数字,移动到index位置,然后index++
- 下个数字只能从index和index后面的位置选取。这样就自动跳过了已经选取过的数字。而不用flag数组进行额外的判断
class Solution {List<List<Integer>> ans = new ArrayList<>();int[] nums;public List<List<Integer>> permute(int[] nums) {this.nums = nums;backTracking( 0);return ans;}public void backTracking(int index){if (index == nums.length) {List<Integer> list = new ArrayList<>();for( int num : nums ) list.add(num);ans.add(list);}else {for (int j = index; j < nums.length; j++) {swap(nums, index, j);backTracking(index + 1);swap(nums, j, index);}}}private void swap(int[] nums, int i, int j){if (i == j) return;nums[i] = nums[i] ^ nums[j];nums[j] = nums[i] ^ nums[j];nums[i] = nums[i] ^ nums[j];}}