package com.freetymekiyan.algorithms.level.medium;
import java.util.ArrayList;
import java.util.List;
/**
* Numbers can be regarded as product of its factors. For example,
* <p>
* 8 = 2 x 2 x 2;
* = 2 x 4.
* Write a function that takes an integer n and return all possible combinations of its factors.
* <p>
* Note:
* You may assume that n is always positive.
* Factors should be greater than 1 and less than n.
* <p>
* Examples:
* input: 1
* output:
* []
* input: 37
* output:
* []
* input: 12
* output:
* |[
* | [2, 6],
* | [2, 2, 3],
* | [3, 4]
* |]
* input: 32
* output:
* |[
* | [2, 16],
* | [2, 2, 8],
* | [2, 2, 2, 4],
* | [2, 2, 2, 2, 2],
* | [2, 4, 4],
* | [4, 8]
* |]
* <p>
* Company Tags: LinkedIn, Uber
* Tags: Backtracking
* Similar Problems: (M) Combination Sum
*/
public class FactorCombinations {
/**
* Backtracking.
* Factors are from 2 to sqrt(n), inclusive.
*/
public List<List<Integer>> getFactors(int n) {
List<List<Integer>> factors = new ArrayList<>();
backtrack(factors, n, 2, new ArrayList<>());
return factors;
}
/**
* Stop condition:
* n is 1, return. If have at least two factors, dereference and add to result.
* Visit:
* For each i from start to sqrt(n):
* | If n is divisible by i:
* | Add i to factors.
* | backtrack on n / i, starting from i. (12 -> 2, 2, 3)
* | Reset.
* | If n is not divisible by i, skip.
* Special case:
* Besides [start, sqrt(n)], n itself can also be a factor.
*/
private void backtrack(List<List<Integer>> res, int n, int start, List<Integer> factors) {
if (n == 1) {
if (factors.size() > 1) { // If n=1, return empty list.
res.add(new ArrayList<>(factors));
}
return;
}
for (int i = start; i <= (int) Math.sqrt(n); i++) {
if (n % i == 0) {
factors.add(i);
backtrack(res, n / i, i, factors);
factors.remove(factors.size() - 1);
}
}
int i = n; // ===> here, change 2
factors.add(i);
backtrack(res, n / i, i, factors);
factors.remove(factors.size() - 1);
}
}