For anyone stumped by why this change is necessary, it's because you should not continue exploring (recursing) when you know that there won't be enough numbers left until n to fill the needed k slots. If n = 10, k = 5, and you're in the outermost level of recursion, you choose only i = 1...6 , because if you pick i=7 and go into backTracking() you only have 8,9,10 to pick from, so at most you will get [7,8,9,10]... but we need 5 elements!
classSolution {publicList<List<Integer>> combine(int n,int k) {List<List<Integer>> result =newArrayList<>();backtrack(result,newArrayList<>(),1, n, k);return result; }privatevoidbacktrack(List<List<Integer>> result,List<Integer> tempList,int start,int n,int k) {if (k ==0) {result.add(newArrayList<>(tempList)); } else {for (int i = start; i <= n-k+1; i++) {tempList.add(i);backtrack(result, tempList, i+1, n, k -1);tempList.remove(tempList.size() -1); } } }}
time: O( k*c(n, k))
space: O( k*c(n, k))
use <= n
classSolution {publicList<List<Integer>> combine(int n,int k) {// use backtracking// 1, 2, 3, 4 k=2// 2 3 4 3. 4 4List<List<Integer>> res =newArrayList<>();helper(res,newArrayList<>(), n, k,1);return res; }privatevoidhelper(List<List<Integer>> res,List<Integer> list,int n,int k,int start) {if (k ==0) {res.add(newArrayList<>(list));return; }for (int i = start; i <= n; i++) {list.add(i);helper(res, list, n, k-1, i +1);list.remove(list.size()-1); } }}