Skip to content

Commit e7e5ab2

Browse files
committed
candy(糖果问题)
1 parent 1f25642 commit e7e5ab2

File tree

8 files changed

+133
-10
lines changed

8 files changed

+133
-10
lines changed

LeetCode/Doc/单词切分2.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ dict =["cat", "cats", "and", "sand", "dog"].
2828

2929
## 解题思路
3030

31-
我们从某一个位置index将s切分为前后两个部分,分别记为s1和s2,如果s1在dict中,我们去计算s2计算的结果,然后将s2切分的结果与s1合并即可,如果s2不能切割,我们就从index+1继续对s进行切割,实际是一种dfs的思想,核心思想如下:
31+
我们从某一个位置`index``s`切分为前后两个部分,分别记为`s1``s2`,如果`s1``dict`中,我们去计算`s2`计算的结果,然后将`s2`切分的结果与`s1`合并即可,如果`s2`不能切割,我们就从`index+1`继续对`s`进行切割,实际是一种`dfs`的思想,核心思想如下:
3232

3333
```java
3434
ArrayList<String> wordBreak(String s, Set<String> dict){
@@ -47,14 +47,14 @@ ArrayList<String> wordBreak(String s, Set<String> dict){
4747
}
4848
```
4949

50-
这样虽然可以解决问题,但是有点小瑕疵,考虑:s="abcdefg",dict={"bc","def","g"},那么:
50+
这样虽然可以解决问题,但是有点小瑕疵,考虑:`s="abcdefg"`,`dict={"bc","def","g"}`,那么:
5151

5252
- index=1 s1=a s2=bcdefg ,切割bcdefg
5353
- Index=2 s1=ab s2=cdefg,切割cdefg
5454
- index=3 s1=abc s2=defg,切割defg
5555
- ...
5656

57-
注意,第一步切割bcdefg的时候递归调用了wordBreak,在切割bcdefg的时候也会切割cdefg、defgefg、fg、g,然后下面几步也是类似的操作,所以说下面几步实际上做了一部分重复的工作,为了避免这种重复的工作,我们可以使用Map,将s与其切分的结果存下来,这样下次再遇到s的时候直接从map中取之前分好的结果就行了,不用做重复操作。
57+
注意,第一步切割`bcdefg`的时候递归调用了`wordBreak`,在切割`bcdefg`的时候也会切割`cdefg``defg``efg``fg``g`,然后下面几步也是类似的操作,所以说下面几步实际上做了一部分重复的工作,为了避免这种重复的工作,我们可以使用`Map`,将`s`与其切分的结果存下来,这样下次再遇到`s`的时候直接从`map`中取之前分好的结果就行了,不用做重复操作。
5858

5959

6060
## 代码

LeetCode/Doc/糖果问题.md

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# candy(糖果问题)
2+
3+
<center>知识点:动态规划</center>
4+
5+
6+
## 题目描述
7+
There are N children standing in a line. Each child is assigned a rating value.
8+
9+
You are giving candies to these children subjected to the following requirements:
10+
11+
Each child must have at least one candy.
12+
Children with a higher rating get more candies than their neighbors.
13+
What is the minimum candies you must give?
14+
15+
有n个小孩站成了一行,每一个孩子都有一个等级值,你现在要给这些孩子按照以下原则分糖果:
16+
17+
每一个小孩必须最少分到一个糖果;
18+
拥有更高等级值的孩子必须比他相邻的孩子分的糖果多。
19+
20+
请问你最少需要多少糖果?
21+
22+
23+
## 解题思路
24+
rating={1,2,5,3,9,2}
25+
candyArray={1,1,1,1,1,1}
26+
采用只加不减的策略,扫描2遍:
27+
第一遍从左向右扫描,保证右边孩子如果优先级比左边孩子大就让右边孩子的糖果数比左边孩子多1,这样可以保证从左到右孩子的糖果分布式符合要求的;
28+
第二标从右向左扫描,保证左边孩子如果优先级比右边孩子大就让左边孩子的糖果数比左边孩子多1,这样可以保证从右到左孩子的糖果分布式符合要求的;
29+
走完上面两步之后,可以保证不管是从左往右走还是从右往左走,孩子们的糖果分配都是符合要求的,最后将candyArray求和返回即可。
30+
31+
32+
## 代码
33+
34+
核心代码:
35+
```java
36+
public int candy(int[] ratings) {
37+
38+
39+
int n = ratings.length;
40+
int[] candyArray = new int[n];
41+
//第0个孩子初始分配1个糖果
42+
candyArray[0] = 1;
43+
for (int index = 1; index < ratings.length; index++) {
44+
45+
//如果右边孩子的优先级大于左边孩子的优先级
46+
if (ratings[index] > ratings[index - 1]) {
47+
//右边孩子分配的糖果数更新为左边孩子分配的糖果数加1
48+
candyArray[index] = candyArray[index - 1] + 1;
49+
} else {
50+
//如果右边孩子的优先级不大于左边孩子的优先级,将右边孩子的糖果数分配为1
51+
candyArray[index] = 1;
52+
}
53+
}
54+
55+
int sum = candyArray[ratings.length - 1];
56+
for (int index = ratings.length - 2; index >= 0; index--) {
57+
//如果左边孩子的优先级大于右边孩子的优先级且左边孩子分配的糖果小于等于右边孩子分配的糖果
58+
if (ratings[index] > ratings[index + 1] && candyArray[index] <= candyArray[index + 1]) {
59+
//左边孩子分配的糖果数更新为右边孩子的糖果数加1
60+
candyArray[index] = candyArray[index + 1] + 1;
61+
}
62+
sum += candyArray[index];
63+
}
64+
return sum;
65+
}
66+
67+
```
68+
[这里](../src/sixteen/Solution.java)
Binary file not shown.
Binary file not shown.

LeetCode/src/fifteen/Solution.java

+12-6
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@
77
public class Solution {
88
public int singleNumber(int[] A) {
99

10-
int a = 0;//只出现过1次的位
11-
int b = 0;//出现过2次的位
12-
int c;//出现过三次的位
10+
//只出现过1次的位
11+
int a = 0;
12+
//出现过2次的位
13+
int b = 0;
14+
//出现过三次的位
15+
int c;
1316
for (int index = 0; index < A.length; index++) {
14-
b = b | (a & A[index]);//之前的b或上现在的出现了2次的位
15-
a = a ^ A[index];//只出现过1次的位
17+
//之前的b或上现在的出现了2次的位
18+
b = b | (a & A[index]);
19+
//只出现过1次的位
20+
a = a ^ A[index];
1621
c = a & b;
17-
a = a & (~c);//抹去出现了3次的bits,~c将原来是1的都变为0,这样那些为与完之后结果一定是0,原来为0的变为1,这样与的结果由a决定
22+
//抹去出现了3次的bits,~c将原来是1的都变为0,这样那些为与完之后结果一定是0,原来为0的变为1,这样与的结果由a决定
23+
a = a & (~c);
1824
b = b & (~c);
1925

2026
}

LeetCode/src/sixteen/Solution.java

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package sixteen;
2+
3+
/**
4+
* @author dmrfcoder
5+
* @date 2019/4/10
6+
*/
7+
public class Solution {
8+
public int candy(int[] ratings) {
9+
10+
11+
int n = ratings.length;
12+
int[] candyArray = new int[n];
13+
//第0个孩子初始分配1个糖果
14+
candyArray[0] = 1;
15+
for (int index = 1; index < ratings.length; index++) {
16+
17+
//如果右边孩子的优先级大于左边孩子的优先级
18+
if (ratings[index] > ratings[index - 1]) {
19+
//右边孩子分配的糖果数更新为左边孩子分配的糖果数加1
20+
candyArray[index] = candyArray[index - 1] + 1;
21+
} else {
22+
//如果右边孩子的优先级不大于左边孩子的优先级,将右边孩子的糖果数分配为1
23+
candyArray[index] = 1;
24+
}
25+
}
26+
27+
int sum = candyArray[ratings.length - 1];
28+
for (int index = ratings.length - 2; index >= 0; index--) {
29+
//如果左边孩子的优先级大于右边孩子的优先级且左边孩子分配的糖果小于等于右边孩子分配的糖果
30+
if (ratings[index] > ratings[index + 1] && candyArray[index] <= candyArray[index + 1]) {
31+
//左边孩子分配的糖果数更新为右边孩子的糖果数加1
32+
candyArray[index] = candyArray[index + 1] + 1;
33+
}
34+
sum += candyArray[index];
35+
}
36+
return sum;
37+
}
38+
39+
40+
public static void main(String[] args) {
41+
42+
int[] ratings = {1, 0, 2};
43+
44+
Solution solution = new Solution();
45+
int a = solution.candy(ratings);
46+
System.out.println(a);
47+
}
48+
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
- [copy-list-with-random-pointer(拷贝具有随机指针的链表)](./LeetCode/Doc/拷贝具有随机指针的链表.md)
158158
- [single-number(出现一次的数)](./LeetCode/Doc/出现一次的数.md)
159159
- [**single-number-ii(出现一次的数2)**](./LeetCode/Doc/出现一次的数2.md)
160+
- [candy(糖果问题)](./LeetCode/Doc/糖果问题.md)
160161

161162

162163

SwordToOffer/Doc/整数中1出现的次数.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55

66
## 题目描述
7-
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
7+
求出1 ~ 13的整数中1出现的次数,并算出100 ~ 1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
88
## 解题思路
99
### 思路一
1010
观察规律,以百位上出现1的次数为例说明,假设n大于等于100且百位上的数为k,则:

0 commit comments

Comments
 (0)