Skip to content

Commit ac8143e

Browse files
committed
贪心
1 parent 21e5c07 commit ac8143e

File tree

1 file changed

+320
-0
lines changed

1 file changed

+320
-0
lines changed

Diff for: leetcode算法之贪心.md

+320
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
今天来盘一盘 **贪心算法 ** 这类题目
2+
3+
4+
5+
使用**python**刷题分类整理的笔记,请参考: [https://github.com/lxztju/leetcode-algorithm/tree/v1](https://github.com/lxztju/leetcode-algorithm/tree/v1)
6+
7+
## 贪心算法
8+
贪心算法是指每步都选择最优的策略,以此达到全局的最优。**局部最优—>全局最优**
9+
10+
贪心策略的选择必须具备**无后效性**,也就是说某个状态以前的过程不会影响以后的状态,只与当前状态有关。
11+
12+
* 455 分发饼干 (Easy)
13+
* 121 买卖股票的最佳时机 (Easy)
14+
* 122 买卖股票的最佳时机 II (Easy)
15+
* 605 种花问题 (Easy)
16+
* 665 非递减数列 (Easy)
17+
* 53 最大子序和 (Easy)
18+
* 435 无重叠区间 (Medium)
19+
* 452 用最少数量的箭引爆气球 (Medium)
20+
* 406 根据身高重建队列(Medium)
21+
* 763 划分字母区间 (Medium)
22+
23+
24+
#### 455 分发饼干 (Easy)
25+
* 二者排序之后采用双指针比较。
26+
```c++
27+
class Solution {
28+
public:
29+
int findContentChildren(vector<int>& g, vector<int>& s) {
30+
// 分别将二者排序
31+
sort(g.begin(), g.end());
32+
sort(s.begin(), s.end());
33+
int i = 0, j = 0;
34+
int res = 0;
35+
while (i < g.size() && j < s.size()){
36+
if (s[j] >= g[i]){
37+
i++;
38+
res++;
39+
}
40+
j++;
41+
}
42+
return res;
43+
}
44+
};
45+
```
46+
47+
#### 121 买卖股票的最佳时机 (Easy)
48+
49+
```c++
50+
class Solution {
51+
public:
52+
int maxProfit(vector<int>& prices) {
53+
// 暴力法
54+
// 双重循环,从第i天买入可以获得的最大利润,计算最大值
55+
int maxprofit = 0;
56+
for ( int i = 0; i < prices.size() - 1; i++){
57+
for (int j = i + 1; j < prices.size(); j++){
58+
int profit = prices[j] - prices[i];
59+
maxprofit = max(profit, maxprofit);
60+
}
61+
}
62+
return maxprofit;
63+
}
64+
};
65+
```
66+
67+
```c++
68+
class Solution {
69+
public:
70+
int maxProfit(vector<int>& prices) {
71+
// 使用minprice变量保存当前天之前的最低价格, 如果在此之前采用最低价格买入,那么当前卖出的利润最大
72+
int maxprofit = 0;
73+
int minprice = INT_MAX;
74+
for(auto price : prices){
75+
minprice = min(minprice, price);
76+
maxprofit = max(maxprofit, price - minprice);
77+
}
78+
return maxprofit;
79+
}
80+
};
81+
```
82+
83+
#### 122 买卖股票的最佳时机 II (Easy)
84+
* 与上一题的主要区别就是,可以多次交易
85+
* 也就是当前只要获利为正就可以交易。
86+
87+
88+
```c++
89+
class Solution {
90+
public:
91+
int maxProfit(vector<int>& prices) {
92+
int ans = 0;
93+
int n = prices.size();
94+
for (int i = 1; i < n; ++i) {
95+
ans += max(0, prices[i] - prices[i - 1]);
96+
}
97+
return ans;
98+
}
99+
};
100+
```
101+
102+
#### 605 种花问题 (Easy)
103+
```c++
104+
class Solution {
105+
public:
106+
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
107+
// 贪心的种植, 可以种植的位置,直接众,只要左右联测均为0,就可以种植。
108+
// 需要考虑首尾的两个元素的特殊情况。将首尾各补上0
109+
int res = 0;
110+
for (int i = 0; i< flowerbed.size(); i++){
111+
int left = (i == 0) ? 0 : flowerbed[i-1];
112+
int right = (i == flowerbed.size()-1) ? 0 : flowerbed[i+1];
113+
if (left == 0 && right == 0 && flowerbed[i] == 0){
114+
// cout<<res<<" " <<i<<endl;
115+
res++;
116+
flowerbed[i] = 1;
117+
}
118+
}
119+
return res >= n;
120+
}
121+
};
122+
```
123+
#### 665 非递减数列 (Easy)
124+
* 遇到nums[i]>nums[i+1]需要将nums[i]变小或者nums[i+1]变大
125+
* 如果nums[i + 1] < nums[i - 1],需要将nums[i+1]变大
126+
* 其他情况下nums[i]变小
127+
128+
```c++
129+
class Solution {
130+
public:
131+
bool checkPossibility(vector<int>& nums) {
132+
int cnt = 0;
133+
for (int i = 0; i < nums.size()-1 && cnt < 2; i++) {
134+
if (nums[i] > nums[i + 1]) {
135+
cnt++;
136+
if (i > 0 && nums[i + 1] < nums[i - 1]) {
137+
nums[i + 1] = nums[i];
138+
}
139+
else {
140+
nums[i] = nums[i + 1];
141+
}
142+
}
143+
}
144+
return cnt < 2;
145+
}
146+
};
147+
```
148+
#### 53 最大子序和 (Easy)
149+
```c++
150+
class Solution {
151+
public:
152+
int maxSubArray(vector<int>& nums) {
153+
// 暴力法
154+
int maxnum = nums[0];
155+
int tmp = 0;
156+
for (int i = 0; i < nums.size(); i++){
157+
tmp = nums[i];
158+
maxnum = max(maxnum, tmp);
159+
for (int j = i+1; j < nums.size(); j++){
160+
tmp += nums[j];
161+
maxnum = max(maxnum, tmp);
162+
}
163+
}
164+
return maxnum;
165+
}
166+
};
167+
```
168+
169+
170+
```c++
171+
class Solution {
172+
public:
173+
int maxSubArray(vector<int>& nums) {
174+
// 动态规划
175+
int maxnum = nums[0];
176+
vector<int> dp(nums.size(), 0); // dp表示到i位置的最长子序和。
177+
dp[0] = nums[0];
178+
for (int i = 1; i< nums.size(); i++){
179+
dp[i] = max(nums[i], dp[i-1] + nums[i]);
180+
maxnum = max(dp[i], maxnum);
181+
}
182+
183+
return maxnum;
184+
}
185+
};
186+
```
187+
188+
#### 435 无重叠区间 (Medium)
189+
```c++
190+
class Solution {
191+
public:
192+
// 按照区间右边界排序
193+
static bool cmp (const vector<int>& a, const vector<int>& b) {
194+
return a[1] < b[1];
195+
}
196+
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
197+
if (intervals.size() == 0) return 0;
198+
sort(intervals.begin(), intervals.end(), cmp);
199+
200+
int cnt = 0;
201+
for (int i = 1; i < intervals.size(); i++) {
202+
if (intervals[i][0] < intervals[i - 1][1]) {
203+
cnt++;
204+
intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]);
205+
}
206+
}
207+
return cnt;
208+
}
209+
};
210+
211+
212+
```
213+
#### 452 用最少数量的箭引爆气球 (Medium)
214+
```c++
215+
class Solution {
216+
public:
217+
// 按照区间的右端点排序
218+
static bool cmp(const vector<int>& a, const vector<int>& b){
219+
return a[1] < b[1];
220+
}
221+
int findMinArrowShots(vector<vector<int>>& points) {
222+
// 与上一题的最大不重叠区间的问题实际是一样的
223+
if(points.size() < 2) return points.size();
224+
sort(points.begin(), points.end(), cmp);
225+
int cnt = 1;
226+
for (int i = 1; i < points.size(); i++){
227+
if (points[i][0] > points[i-1][1])
228+
cnt++;
229+
else
230+
points[i][1] = min(points[i][1], points[i-1][1]);
231+
}
232+
return cnt;
233+
}
234+
};
235+
```
236+
#### 406 根据身高重建队列(Medium)
237+
```c++
238+
class Solution {
239+
public:
240+
static bool cmp(const vector<int> a, const vector<int> b) {
241+
if (a[0] == b[0]) return a[1] < b[1];
242+
return a[0] > b[0];
243+
}
244+
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
245+
sort (people.begin(), people.end(), cmp);
246+
vector<vector<int>> que;
247+
for (int i = 0; i < people.size(); i++) {
248+
int position = people[i][1];
249+
que.insert(que.begin() + position, people[i]);
250+
}
251+
return que;
252+
}
253+
};
254+
```
255+
#### 763 划分字母区间 (Medium)
256+
```c++
257+
class Solution {
258+
public:
259+
static bool cmp(const vector<int>& a, const vector<int>& b){
260+
return a[0] < b[0];
261+
}
262+
vector<int> partitionLabels(string S) {
263+
// 这个题目实际上还是求最大的不重合区间的个数
264+
// 首先遍历字符串S,求出每个字符首次与最后一次出现的次数
265+
// 这样还是一个不重合区间的个数问题
266+
267+
vector<vector<int>> boards(26, vector<int>(2, -1));
268+
for (int i = 0; i < S.size(); i++){
269+
int index = S[i] - 'a';
270+
if (boards[index][0] == -1){
271+
boards[index][0] = i;
272+
boards[index][1] = i;
273+
}
274+
else
275+
boards[index][1] = i;
276+
}
277+
278+
sort(boards.begin(), boards.end(), cmp);
279+
280+
vector<int> res;
281+
282+
int i = 0;
283+
while (i < 26){
284+
if (boards[i][1] != -1) break;
285+
i++;
286+
}
287+
288+
int min_board = boards[i][0];
289+
int max_board = boards[i][1];
290+
// i++;
291+
while ( i < 26){
292+
if ( boards[i][0] > max_board){
293+
res.push_back(max_board - min_board + 1);
294+
min_board = boards[i][0];
295+
}
296+
297+
max_board = max(max_board,boards[i][1]);
298+
i++;
299+
}
300+
res.push_back(max_board - min_board + 1);
301+
return res;
302+
}
303+
};
304+
```
305+
306+
307+
308+
309+
310+
## 更多分类刷题资料
311+
312+
* 微信公众号: 小哲AI
313+
314+
![wechat_QRcode](https://img-blog.csdnimg.cn/20210104185413204.jpg)
315+
316+
* GitHub地址: [https://github.com/lxztju/leetcode-algorithm](https://github.com/lxztju/leetcode-algorithm)
317+
* csdn博客: [https://blog.csdn.net/lxztju](https://blog.csdn.net/lxztju)
318+
* 知乎专栏: [https://www.zhihu.com/column/c_1101089619118026752](https://www.zhihu.com/column/c_1101089619118026752)
319+
* AI研习社专栏:[https://www.yanxishe.com/column/109](https://www.yanxishe.com/column/109)
320+

0 commit comments

Comments
 (0)