Every Possible Ordering of a Set of Distinct Numbers
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 7 - ◆
-20 ≤ nums[i] ≤ 20, and every value in nums is distinct - ◆
Results are returned sorted in ascending (lexicographic) order for a stable, checkable answer
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Rebuild the Remaining Elements at Every Step
BruteTrack which elements are still available as an explicit list rather than a fixed-size flag array. At each node, try every element still in that list: remove it to build a brand-new "remaining" list for the recursive call, append it to the path, recurse, then pop it back off the path afterward. Correct, but a fresh remaining-list is allocated and copied at every single node — O(n) wasted work per node on top of the n! · n work that's unavoidable just to write out every permutation.
O(n! · n²)O(n! · n)1class Solution {
2 public int[][] allPermutationsOf(int[] nums) {
3 List<int[]> result = new ArrayList<>();
4 List<Integer> remaining = new ArrayList<>();
5 for (int v : nums) remaining.add(v);
6 generate(remaining, new ArrayList<>(), result);
7 result.sort((a, b) -> {
8 for (int i = 0; i < a.length; i++) {
9 if (a[i] != b[i]) return a[i] - b[i];
10 }
11 return 0;
12 });
13 return result.toArray(new int[0][]);
14 }
15
16 private void generate(List<Integer> remaining, List<Integer> path, List<int[]> result) {
17 if (remaining.isEmpty()) {
18 int[] row = new int[path.size()];
19 for (int j = 0; j < row.length; j++) row[j] = path.get(j);
20 result.add(row);
21 return;
22 }
23 for (int i = 0; i < remaining.size(); i++) {
24 List<Integer> nextRemaining = new ArrayList<>(remaining);
25 nextRemaining.remove(i);
26 path.add(remaining.get(i));
27 generate(nextRemaining, path, result);
28 path.remove(path.size() - 1);
29 }
30 }
31}Optimal — Shared Path With a Used-Flags Array
OptimalKeep one fixed-size boolean array marking which positions of nums are already in the current path, instead of rebuilding a filtered list every time. At each node, scan the flags and try every not-yet-used index: mark it used, append it to a single shared path array, recurse, then unmark it and pop it back off. No list is ever allocated or copied — checking and flipping a flag is O(1), so the only work done is exactly what's needed to write out each permutation.
O(n! · n)O(n)1class Solution {
2 public int[][] allPermutationsOf(int[] nums) {
3 List<int[]> result = new ArrayList<>();
4 boolean[] used = new boolean[nums.length];
5 List<Integer> path = new ArrayList<>();
6 backtrack(nums, used, path, result);
7 result.sort((a, b) -> {
8 for (int i = 0; i < a.length; i++) {
9 if (a[i] != b[i]) return a[i] - b[i];
10 }
11 return 0;
12 });
13 return result.toArray(new int[0][]);
14 }
15
16 private void backtrack(int[] nums, boolean[] used, List<Integer> path, List<int[]> result) {
17 if (path.size() == nums.length) {
18 int[] row = new int[path.size()];
19 for (int j = 0; j < row.length; j++) row[j] = path.get(j);
20 result.add(row);
21 return;
22 }
23 for (int i = 0; i < nums.length; i++) {
24 if (used[i]) continue;
25 used[i] = true;
26 path.add(nums[i]);
27 backtrack(nums, used, path, result);
28 path.remove(path.size() - 1);
29 used[i] = false;
30 }
31 }
32}