Numbers can be regarded as product of its factors. For example,
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.
Note:
- You may assume that n is always positive.
- Factors should be greater than 1 and less than n.
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] ]
这道题需要注意的是如何避免重复,需要在backtracking的inputs里加一个sentinel,在backtracking的循环过程中从sentinel开始加。
public IList<IList<int>> GetFactors(int n) { var res = new List<IList<int>>(); if(n ==0) return res; BackTracking(n,new List<int>(),res,2); return res; } private void BackTracking(int n, List<int> cur, IList<IList<int>> res,int last) { if(n==1) { if(cur.Count()>1) res.Add(new List<int>(cur)); } else { for(int i = last;i<= n;i++) { if(n%i ==0) { cur.Add(i); BackTracking(n/i,cur,res,i); cur.RemoveAt(cur.Count()-1); } } } }
上面算法是可以优化的,因为一个整数分为两个整数乘积的时候,较小的乘数也不会超过原来数字的平方根。则可以在loop的上界限制为sqrt(n)。
public IList<IList<int>> GetFactors(int n) { var res = new List<IList<int>>(); if(n ==0) return res; BackTracking(n,new List<int>(),res,2); return res; } private void BackTracking(int n, List<int> cur, IList<IList<int>> res,int last) { if(cur.Count()>0) { cur.Add(n); res.Add(new List<int>(cur)); cur.RemoveAt(cur.Count()-1); } for(int i = last;i<= (int)Math.Sqrt(n);i++) { if(n%i ==0) { cur.Add(i); BackTracking(n/i,cur,res,i); cur.RemoveAt(cur.Count()-1); } } }