给一个正整数 n,写一个函数找到若干个完全平方数(比如 1,4,9,...)使得他们的和等于 n。要求为你需要让平方数的个数最少,输出需要的最少的平方数的个数。
格式:
输入每一行输入一个 整数 n,输出每一行输出需要最少的平方数的个数。
样例输入
n = 12
n = 13
样例输出
3
//12 = 4 + 4 + 4
2
//13 = 4 + 9
解题思路,该问题与下楼梯的问题类似,都是斐波那契数列问题
令n = a + b,arr[a]就是a的完美平方数字的组合数组,arr[b]就是b的完美平方数字的组合,arr[n]就是n的完美平方数字的组合
n = 1,arr[1] = [1]
n = 2,n = 1 + 1,因为1的平方是1,所以arr[2] = [1,1]
n = 3,n = 1 + 2,因为1是平方数,2不是平方数,所以找到2的完美平方数的组合arr[2]=[1,1],所有arr[3] = [1,1,1]
n = 4,n = 1 + 3 ,arr[4] = [1,1,1,1]
n = 2 + 2 ,arr[4] = [1,1,1,1]
从上可知arr[4] = [1,1,1,1]
n = 5,n = 1 + 4 ,因为1、4都是平方数,所以arr[5] = [1,4]
n = 2 + 3, 因为2、3都不是平方数,所以arr[5] = [1,1,1,1,1]
从题意可知,arr[5] = [1,4]
从以上推理可知,n = a + b,a的取值范围从1到n/2
1、当a、b都是平方数,arr[n] = [a,b]
2、当a是平方数、b不是平方数,arr[n] = [a,arr[b]]
3、当a不是平方数,b是平方数,arr[n] = [arr[a],b]
4、当a、b都不是平方数,则arr[n] = [arr[a],arr[b]]
对任何一个数字n,找出上述四种情况中,平方数字组合数目最小的那种即可。
代码如下:
package suanfa;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class PowNumber {
public static void main(String[] args) {
Map<Integer, List<Integer>> mapList = compute_v2(20);
Iterator<Integer> ite = mapList.keySet().iterator();
while (ite.hasNext()) {
int key = ite.next();
List<Integer> list = mapList.get(key);
System.out.print(String.format("%-20s", key + "的完美平方数是:"));
for (int i = 0; i < list.size(); i++) {
System.out.print(String.format("%-10d", list.get(i)));
}
System.out.print("\n");
}
}
public static Map<Integer, List<Integer>> compute_v2(int num) {
Map<Integer, List<Integer>> map = new HashMap<>();
map.put(1, Arrays.asList(1));
for (int i = 2; i <= num; i++) {
int c = 1, a = 1, b = i - a;
while (b > 0) {
if (isPowNumber(b)) {
map.put(i, Arrays.asList(a, b));
break;
} else {
List<Integer> l = new LinkedList<Integer>();
l.add(a);
l.addAll(map.get(b));
if (map.get(i) == null || map.get(i).size() > l.size()) {
map.put(i, l);
}
}
c++;
a = (int)Math.pow(c, 2);
b = i - a;
}
}
return map;
}
public static Map<Integer, List<Integer>> compute(int num) {
Map<Integer, List<Integer>> map = new HashMap<>();
map.put(1, Arrays.asList(1));
for (int i = 2; i <= num; i++) {
int end = i / 2;
for (int a = 1; a <= end; a++) {
int b = i - a;
if (isPowNumber(a) && isPowNumber(b)) {
map.put(i, Arrays.asList(a, b));
break;
} else if (!isPowNumber(a) && isPowNumber(b)) {
List<Integer> l = new LinkedList<Integer>();
l.add(b);
l.addAll(map.get(a));
if (map.get(i) == null || map.get(i).size() > l.size()) {
map.put(i, l);
}
} else if (isPowNumber(a) && !isPowNumber(b)) {
List<Integer> l = new LinkedList<Integer>();
l.add(a);
l.addAll(map.get(b));
if (map.get(i) == null || map.get(i).size() > l.size()) {
map.put(i, l);
}
} else {
List<Integer> l = new LinkedList<Integer>();
l.addAll(map.get(a));
l.addAll(map.get(b));
if (map.get(i) == null || map.get(i).size() > l.size()) {
map.put(i, l);
}
}
}
}
return map;
}
public static boolean isPowNumber(int number) {
double d = Math.sqrt(number);
int i = (int)d;
return d == i;
}
}
结果如下:
1的完美平方数是: 1
2的完美平方数是: 1 1
3的完美平方数是: 1 1 1
4的完美平方数是: 1 1 1 1
5的完美平方数是: 1 4
6的完美平方数是: 1 1 4
7的完美平方数是: 1 1 1 4
8的完美平方数是: 4 4
9的完美平方数是: 1 4 4
10的完美平方数是: 1 9
11的完美平方数是: 1 1 9
12的完美平方数是: 4 4 4
13的完美平方数是: 4 9
14的完美平方数是: 1 4 9
15的完美平方数是: 1 1 4 9
16的完美平方数是: 4 4 4 4
17的完美平方数是: 1 16
18的完美平方数是: 9 9
19的完美平方数是: 1 9 9
20的完美平方数是: 4 16