|
| 1 | +#### 题目描述 |
| 2 | + |
| 3 | +小Q十分富有,拥有非常多的硬币,小Q拥有的硬币是有规律的,对于所有的非负整数K,小Q恰好各有两个面值为2^k的硬币,所有小Q拥有的硬币就是1,1,2,2,4,4,8,8.....小Q有一天去商店购买东西需要支付n元钱,小Q想知道有多少种方案从他拥有的硬币中选取一些拼凑起来恰好是n元(如果两种方案某个面值的硬币选取的个数不一样就考虑为不一样的方案) |
| 4 | + |
| 5 | +#### 分析 |
| 6 | + |
| 7 | +1. 已知n,在已知的可选集合里,取一定个数的元素,使得元素相加和为n。问:有多少种方案? |
| 8 | + |
| 9 | + |
| 10 | +2. 若不考虑可选集合。n = (n-1) + 1 或 (n-2) + 2 或 (n-3) + 3 … (n - x) + x; 共有 n/2 种方案。 |
| 11 | + |
| 12 | +3. 可选集合的特点为 元素都是 2^k (k >= 0) 且 每一个值都有一对。 |
| 13 | + |
| 14 | +4. 所有最终的方案数 count 一定是 小于等于 n/2 的,取决于n的值 比如当n=2时 n/2=1 且 本题中可选方案也是只有 1,1(2^0 + 2^0) |
| 15 | + |
| 16 | +5. 由集合中元素的特点可以联想到 **二进制**。如果将集合中的所有元素都用二进制来表示的话: |
| 17 | + $$ |
| 18 | + 1=2^0=(1)2; 2=2^1=(10)2; 4 = 2^2 = (100)2;..... .(等号最后的数都是二进制表示法) |
| 19 | + $$ |
| 20 | + 集合中的每一个元素都可以表示为 首位为 1 其他位为 0 的二进制数。 |
| 21 | + |
| 22 | +6. 集合中元素是成对出现的,那么可以将集合拆分为完全相同的两部分, 每一个数都可以由二进制中指定位置为1 来表示: |
| 23 | + |
| 24 | + 8 4 2 1 —> 1 1 1 1 |
| 25 | + |
| 26 | + 8 4 2 1 —> 1 1 1 1 |
| 27 | + |
| 28 | + 那么,若目标数 n 为 11.那么 11 = 1 + 10 = 2 + 9 = 3 + 8 = 4 + 7 = 5 + 6; |
| 29 | + |
| 30 | + **a.** 以 **1 + 10** 为例 : 1 的 二进制 1, 10的二进制为 1010 那么 (11) 就相当于 |
| 31 | + |
| 32 | + 取 二进制数 第一位的1, 第四位的1 ,第2位的 1 [**从右往左**] |
| 33 | + |
| 34 | + 即可组成 十进制的11。 |
| 35 | + |
| 36 | + **b.** **2 + 9 = (10)2+ (1001)2** : 取第二位的1, 第四位的1, 从第一位的1 [**从右往左**] |
| 37 | + |
| 38 | + 同理: |
| 39 | + |
| 40 | + **c.** **3 + 8= (11)2+(1000)2** |
| 41 | + |
| 42 | + **d.** **4+7 = (100)2+(111)2** |
| 43 | + |
| 44 | + **e.** **5+6=(101)2+(110)2** |
| 45 | + |
| 46 | + a 和 b ,c 中 其实是同一种方案。可通过**异或运算**进行去重:1^10 == 2^9 == 3^8 |
| 47 | + |
| 48 | + d,e 也是同一种方案。 |
| 49 | + |
| 50 | +#### 解题思路 |
| 51 | + |
| 52 | + 经过以上**分析**,解题思路如下: |
| 53 | + |
| 54 | +1. 求 n/2 = i; |
| 55 | + |
| 56 | +2. i从0开始,因为如果n=4 那么 0+4 也是一种方案,只不过只选择一个 4 而已; |
| 57 | + |
| 58 | +3. 从i=0开始,i<=(n/2), 每次i+1 循环开始:循环中将 i^(n-i)的值放到 Set(无重复元素)中 |
| 59 | + |
| 60 | +4. 最终求 Set的 size大小。就是最终的方案数。 |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +#### 代码实现 |
| 65 | + |
| 66 | +``` |
| 67 | +import java.util.HashSet; |
| 68 | +import java.util.Set; |
| 69 | +
|
| 70 | +public class CoinsOfQy { |
| 71 | +
|
| 72 | + /**测试*/ |
| 73 | + public static void main(String[] args) { |
| 74 | +
|
| 75 | + int n = 11; |
| 76 | + int result = coinsOfQy(n); |
| 77 | + System.out.println(result); |
| 78 | + } |
| 79 | + |
| 80 | + private static int coinsOfQy(int n) { |
| 81 | +
|
| 82 | + Set<Integer> resultSet = new HashSet<>(); |
| 83 | + for (int i =0; i<= n/2; i++){ |
| 84 | + int r = i^(n-i); |
| 85 | + resultSet.add(r); |
| 86 | + } |
| 87 | + return resultSet.size(); |
| 88 | + } |
| 89 | +
|
| 90 | +
|
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | + |
| 98 | +##### |
0 commit comments