|
15 | 15 | ```
|
16 | 16 |
|
17 | 17 | ### 解法
|
| 18 | + |
| 19 | +解法①: |
| 20 | + |
18 | 21 | 将数组的首元素依次与数组的每个元素交换(两元素不相等才进行交换),对于每一轮交换,对后面的数组进行递归调用。当元素只剩下一个时,添加此时的数组到 list 中。
|
19 | 22 |
|
20 | 23 | 注意:第 i 个数字与第 j 个数字交换时,要求[i, j) 中没有与第 j 个数字相等的数。
|
21 | 24 |
|
22 |
| -解法①: |
23 |
| - |
24 | 25 | ```java
|
25 | 26 | class Solution {
|
26 | 27 | public List<List<Integer>> permuteUnique(int[] nums) {
|
@@ -72,6 +73,8 @@ class Solution {
|
72 | 73 |
|
73 | 74 | 解法②:
|
74 | 75 |
|
| 76 | +利用空间换取时间,减少 n^2 复杂度。这里的空间,可以采用数组,或者 HashMap。 |
| 77 | + |
75 | 78 | ```java
|
76 | 79 | class Solution {
|
77 | 80 | public List<List<Integer>> permuteUnique(int[] nums) {
|
@@ -123,4 +126,79 @@ class Solution {
|
123 | 126 | nums[j] = t;
|
124 | 127 | }
|
125 | 128 | }
|
| 129 | +``` |
| 130 | + |
| 131 | +解法➂: |
| 132 | + |
| 133 | +这是非递归的解法。思路就是: |
| 134 | + |
| 135 | +- 先保存升序数组; |
| 136 | +- 找到下一个比该数组大的数组,保存; |
| 137 | +- 直到数组呈降序。 |
| 138 | + |
| 139 | +如何找到下一个数组呢?从后往前,找到第一个升序状态的位置,记为 i-1,在[i, length - 1] 中找到比 nums[i - 1] 大的,且差值最小的元素(如果有多个差值最小且相同的元素,取后者),进行交换。将后面的数组序列升序排列,保存。然后恢复 i,继续循环。 |
| 140 | + |
| 141 | +```java |
| 142 | +class Solution { |
| 143 | + public List<List<Integer>> permuteUnique(int[] nums) { |
| 144 | + List<List<Integer>> list = new ArrayList<>(); |
| 145 | + // 先排序,并添加至 list 中 |
| 146 | + Arrays.sort(nums); |
| 147 | + addList(list, nums); |
| 148 | + permute(list, nums); |
| 149 | + return list; |
| 150 | + } |
| 151 | + |
| 152 | + private void permute(List<List<Integer>> list, int[] nums) { |
| 153 | + int n = nums.length; |
| 154 | + for (int i = n - 1; i > 0; --i) { |
| 155 | + if (nums[i - 1] < nums[i]) { |
| 156 | + // 在数组右边找到比 nums[i - 1] 大的,但差值最小的数的下标 |
| 157 | + // 若有多个最小差值,取后者 |
| 158 | + int index = findMinIndex(nums, i, nums[i - 1]); |
| 159 | + swap(nums, i - 1, index); |
| 160 | + sortArr(nums, i); |
| 161 | + addList(list, nums); |
| 162 | + i = n; |
| 163 | + } |
| 164 | + } |
| 165 | + |
| 166 | + } |
| 167 | + |
| 168 | + private void sortArr(int[] nums, int start) { |
| 169 | + int n = nums.length - 1; |
| 170 | + while (start < n) { |
| 171 | + swap(nums, start, n); |
| 172 | + ++start; |
| 173 | + --n; |
| 174 | + } |
| 175 | + } |
| 176 | + |
| 177 | + private int findMinIndex(int[] nums, int start, int val) { |
| 178 | + int index = start; |
| 179 | + int distance = nums[start] - val; |
| 180 | + for (int i = start; i < nums.length; ++i) { |
| 181 | + if (nums[i] > val && (nums[i] - val <= distance)) { |
| 182 | + distance = nums[i] - val; |
| 183 | + index = i; |
| 184 | + } |
| 185 | + } |
| 186 | + return index; |
| 187 | + } |
| 188 | + |
| 189 | + private void addList(List<List<Integer>> list, int[] nums) { |
| 190 | + List<Integer> tmpList = new ArrayList<>(); |
| 191 | + for (int val : nums) { |
| 192 | + tmpList.add(val); |
| 193 | + } |
| 194 | + list.add(tmpList); |
| 195 | + |
| 196 | + } |
| 197 | + |
| 198 | + private void swap(int[] nums, int i, int j) { |
| 199 | + int t = nums[i]; |
| 200 | + nums[i] = nums[j]; |
| 201 | + nums[j] = t; |
| 202 | + } |
| 203 | +} |
126 | 204 | ```
|
0 commit comments