方法 1:使用数组模拟栈(注释掉的代码)
优点:
使用数组 stack 来存储当前的组合,这种方法在空间上更节省,因为不需要为每个组合创建一个新的列表对象。
直接使用数组索引 stop 来控制当前组合的长度,这种方法在操作上更直接和高效。
缺点:
代码中使用了手动管理的数组,这可能会使代码的可读性和易维护性降低。
在递归回溯时,需要手动管理数组的索引 stop,这增加了代码的复杂性。
性能:
这种方法的性能相对较好,因为它减少了对象创建的开销。在您提供的注释中,这种方法的运行时间为 16ms。
方法 2:使用 LinkedList 作为栈
优点:
使用 LinkedList 来存储当前的组合,这种方法在操作上更简单,因为 LinkedList 提供了方便的 push 和 pop 操作。
代码的可读性更好,因为使用了更常见的数据结构。
缺点:
每次添加或删除元素时,LinkedList 可能需要更多的时间,尤其是当列表很大时。
创建新的 ArrayList 对象来存储每个组合可能会增加额外的空间开销。
性能:
这种方法的性能稍逊于第一种方法,因为它涉及到更多的对象创建和可能的额外开销。在您提供的注释中,这种方法的运行时间为 21ms。
//77. 组合
//模拟栈,16ms
/*public List<List
List<List
int[] stack=new int[k];//记录路径
int stop=-1;
dfsCombine(n,k,res,stack,1,stop);
return res;
}
private void dfsCombine(int n, int k, List<List<Integer>> res,int[] stack,int start,int stop) {if(stop+1 == k) {List<Integer> list=new ArrayList<>();for (int i : stack) {list.add(i);}res.add(list);return;}for (int i = start; i <= n; i++) {if (k-(stop+1)>n-start+1) return;stack[++stop]=i;dfsCombine(n, k, res, stack, i+1,stop);stop--;}
}*/
//21ms
public List<List<Integer>> combine(int n, int k) {List<List<Integer>> res = new ArrayList<List<Integer>>();LinkedList<Integer> stack = new LinkedList<>();//记录路径dfsCombine(n,k,res,stack,1);return res;
}private void dfsCombine(int n, int k, List<List<Integer>> res,LinkedList<Integer> stack,int start) {if(stack.size() == k) {res.add(new ArrayList<>(stack));return;}for (int i = start; i <= n; i++) {if (k-stack.size()>n-start+1) return;stack.push(i);dfsCombine(n, k, res, stack, i+1);stack.pop();}
}