1 介绍
本博客用来记录代码随想录leetcode200题之贪心算法相关题目。
2 训练
题目1:455. 分发饼干
C++代码如下,
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int res = 0;
for (auto x : s) {
if (res < g.size() && x >= g[res]) {
res += 1;
}
}
return res;
}
};
python3代码如下,
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
res = 0
for x in s:
if res < len(g) and x >= g[res]:
res += 1
return res
题目2:376. 摆动序列
C++代码如下,
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n = nums.size();
vector<int> diff;
for (int i = 0; i < n-1; ++i) {
diff.emplace_back(nums[i+1]-nums[i]);
}
int res = 0;
int prex = -2010;
for (auto x : diff) {
if (x == 0) prex += x;
else if (prex == -2010 || prex * x < 0) {
res += 1;
prex = x;
} else prex += x;
}
return res + 1;
}
};
python3代码如下,
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
n = len(nums)
diff = []
for i in range(n-1):
diff.append(nums[i+1]-nums[i])
res = 0
pre = -2010
for x in diff:
if x == 0:
pre += x
elif pre == -2010 or pre * x < 0:
res += 1
pre = x
else:
pre += x
return res + 1
题目3:53. 最大子数组和
C++代码如下,
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = -1e5;
int cur = 0;
for (auto x : nums) {
if (cur <= 0) cur = x;
else cur += x;
res = max(res, cur);
}
return res;
}
};
python3代码如下,
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
res = int(-1e5)
cur = 0
for x in nums:
if cur <= 0:
cur = x
else:
cur += x
res = max(res, cur)
return res
C++代码如下,
贪心写法,
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
vector<int> diff;
for (int i = 0; i < n-1; ++i) {
diff.emplace_back(prices[i+1]-prices[i]);
}
int res = 0;
for (auto x : diff) {
if (x > 0) res += x;
}
return res;
}
};
动态规划写法,
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
vector<vector<int>> dp(n, vector<int>(2, 0));
//状态定义
//dp[i][0]:第i天不持股的最大现金
//dp[i][1]:第i天持股的最大现金
//状态转移
//dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
//dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
//状态初始化
//dp[0][0] = 0
//dp[0][1] = -prices[0]
dp[0][1] = -prices[0];
for (int i = 1; i < n; ++i) {
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]);
}
return dp[n-1][0];
}
};
python3代码如下,
贪心写法,
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
diff = []
for i in range(n-1):
diff.append(prices[i+1]-prices[i])
res = 0
for x in diff:
if x > 0:
res += x
return res
动态规划写法,
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
dp = [[0, 0] for _ in range(n)]
#状态定义
#dp[i][0]: 第i天不持股的最大现金
#dp[i][1]: 第i天持股的最大现金
#状态转移
#dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
#dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
#状态初始化
#dp[0][0] = 0
#dp[0][1] = -prices[0]
dp[0][1] = -prices[0]
for i in range(1,n):
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
return dp[n-1][0]
题目5:55. 跳跃游戏
C++代码如下,
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
int cover = 0;
for (int i = 0; i <= cover; ++i) {
cover = max(cover, nums[i]+i);
if (cover >= n-1) return true;
}
return false;
}
};
python3代码如下,
class Solution:
def canJump(self, nums: List[int]) -> bool:
n = len(nums)
cover = 0
i = 0
while i <= cover:
cover = max(nums[i] + i, cover)
if cover >= n-1:
return True
i += 1
return False
题目6:45. 跳跃游戏 II
C++代码如下,
class Solution {
public:
int jump(vector<int>& nums) {
int n = nums.size();
int res = 0;
int i = 0;
while (i < n-1) {
if (i + nums[i] >= n-1) {
res += 1;
return res;
}
int t = i + 1;
for (int j = i+1; j <= i+nums[i]; ++j) {
if (t + nums[t] < j + nums[j]) {
t = j;
}
}
res += 1;
i = t; //更新i
}
return res;
}
};
python3代码如下,
class Solution:
def jump(self, nums: List[int]) -> int:
n = len(nums)
res = 0
i = 0
while i < n-1:
if i + nums[i] >= n - 1:
res += 1
break
length = nums[i]
#[i+1,i+length]
t = i + 1
for j in range(i+1,i+length+1):
if nums[t] + t < nums[j] + j:
t = j
res += 1
i = t #更新i
return res
C++代码如下,
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
int n = nums.size();
sort(nums.begin(), nums.end(), [](int x, int y) {
return abs(x) > abs(y);
});
for (int i = 0; i < n; ++i) {
if (k > 0 && nums[i] < 0) {
nums[i] *= -1;
k -= 1;
}
}
if (k % 2 == 1) {
nums[n-1] *= -1;
}
return accumulate(nums.begin(), nums.end(), 0);
}
};
python3代码如下,
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
n = len(nums)
nums.sort(key = lambda x : abs(x), reverse = True)
for i in range(n):
if k > 0 and nums[i] < 0:
nums[i] *= -1
k -= 1
if k % 2 == 1:
nums[-1] *= -1
return sum(nums)
题目8:134. 加油站
C++代码如下,
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n = gas.size();
int currSum = 0;
int totalSum = 0;
int res = 0;
for (int i = 0; i < n; ++i) {
int t = gas[i] - cost[i];
if (currSum < 0) {
currSum = 0;
res = i;
}
currSum += t;
totalSum += t;
}
if (totalSum < 0) res = -1;
return res;
}
};
python3代码如下,
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
totalSum = 0
curSum = 0
n = len(gas)
res = 0
for i in range(n):
t = gas[i] - cost[i]
if curSum < 0:
curSum = 0
res = i
curSum += t
totalSum += t
if totalSum < 0:
res = -1
return res
题目9:135. 分发糖果
C++代码如下,
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
vector<int> nums(n, 1);
for (int i = 1; i < n; ++i) {
if (ratings[i] > ratings[i-1]) {
nums[i] = nums[i-1] + 1;
}
}
for (int i = n-2; i >= 0; --i) {
if (ratings[i] > ratings[i+1]) {
nums[i] = max(nums[i], nums[i+1] + 1);
}
}
return accumulate(nums.begin(), nums.end(), 0);
}
};
python3代码如下,
class Solution:
def candy(self, ratings: List[int]) -> int:
n = len(ratings)
nums = [1] * n
for i in range(1,n):
if ratings[i] > ratings[i-1]:
nums[i] = nums[i-1] + 1
for i in range(n-2,-1,-1):
if ratings[i] > ratings[i+1]:
nums[i] = max(nums[i], nums[i+1] + 1)
return sum(nums)
题目10:860. 柠檬水找零
C++代码如下,
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
vector<int> cur = {0, 0, 0};
//cur[0]表示5元纸币的数目
//cur[1]表示10元纸币的数目
//cur[2]表示20元纸币的数目
for (auto x : bills) {
if (x == 5) {
cur[0] += 1;
} else if (x == 10) {
cur[0] -= 1;
cur[1] += 1;
if (cur[0] < 0) return false;
} else {
if (cur[1] > 0) {
cur[1] -= 1;
cur[0] -= 1;
} else {
cur[0] -= 3;
}
if (cur[0] < 0 || cur[1] < 0) return false;
cur[2] += 1;
}
}
return true;
}
};
python3代码如下,
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
cur = [0, 0, 0]
#cur[0]表示5元纸币的数目
#cur[1]表示10元纸币的数目
#cur[2]表示20元纸币的数目
for x in bills:
if x == 5:
cur[0] += 1
elif x == 10:
cur[0] -= 1
if cur[0] < 0:
return False
cur[1] += 1
else:
if cur[1] > 0:
cur[1] -= 1
cur[0] -= 1
else:
cur[0] -= 3
if cur[0] < 0 or cur[1] < 0:
return False
cur[2] += 1
return True
题目11:406. 根据身高重建队列
C++代码如下,
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), [](vector<int> a, vector<int> b) {
return a[0] > b[0] || (a[0] == b[0] && a[1] < b[1]);
});
vector<vector<int>> res;
for (auto x : people) {
int idx = x[1];
res.insert(res.begin() + idx, x);
}
return res;
}
};
python3代码如下,
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
people.sort(key = lambda x : (x[0],-x[1]), reverse = True)
res = []
for x in people:
i = x[1]
res.insert(i, x)
return res
题目12:452. 用最少数量的箭引爆气球
C++代码如下,
class Solution {
public:
int findMinArrowShots(vector<vector<int>>& points) {
int n = points.size();
sort(points.begin(), points.end());
if (n == 0) { //特判
return 0;
}
int res = 1;
for (int i = 1; i < n; ++i) {
if (points[i][0] > points[i-1][1]) {
res += 1;
} else {
points[i][1] = min(points[i][1], points[i-1][1]);
}
}
return res;
}
};
python3代码如下,
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
n = len(points)
points.sort()
if n == 0: #特判
return 0
res = 1
for i in range(1,n):
if points[i][0] > points[i-1][1]:
res += 1
else:
points[i][1] = min(points[i][1], points[i-1][1])
return res
题目13:435. 无重叠区间
C++代码如下,
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
int n = intervals.size();
int res = 0;
for (int i = 1; i < n; ++i) {
if (intervals[i][0] < intervals[i-1][1]) {
res += 1;
intervals[i][1] = min(intervals[i][1], intervals[i-1][1]);
}
}
return res;
}
};
python3代码如下,
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort()
n = len(intervals)
res = 0
for i in range(1,n):
if intervals[i][0] < intervals[i-1][1]:
intervals[i][1] = min(intervals[i][1], intervals[i-1][1])
res += 1
return res
题目14:763. 划分字母区间
C++代码如下,
class Solution {
public:
vector<int> partitionLabels(string s) {
int n = s.size();
unordered_map<char, int> map_c_ei;
for (int i = 0; i < n; ++i) {
map_c_ei[s[i]] = i;
}
int left = 0, right = 0;
vector<int> res;
for (int i = 0; i < n; ++i) {
right = max(right, map_c_ei[s[i]]);
if (i == right) {
res.emplace_back(right-left+1);
left = right + 1;
}
}
return res;
}
};
python3代码如下,
Carl哥写法,
class Solution:
def partitionLabels(self, s: str) -> List[int]:
map_c_ei = collections.defaultdict(int)
n = len(s)
for i in range(n):
map_c_ei[s[i]] = i
res = []
left = 0
right = 0
for i in range(n):
right = max(right, map_c_ei[s[i]])
if i == right:
res.append(right-left+1)
left = right + 1
return res
区间解法,
class Solution:
def partitionLabels(self, s: str) -> List[int]:
n = len(s)
map_c_si = collections.defaultdict(int)
map_c_ei = collections.defaultdict(int)
for i in range(n):
map_c_ei[s[i]] = i
for i in range(n-1,-1,-1):
map_c_si[s[i]] = i
intervals = []
for i in range(26):
c = chr(ord('a') + i)
if c in map_c_si:
si = map_c_si[c]
ei = map_c_ei[c]
intervals.append([si,ei])
intervals.sort()
m = len(intervals)
res = []
i, j = intervals[0][0], intervals[0][1]
for k in range(1,m):
ni = intervals[k][0]
nj = intervals[k][1]
if ni > j:
res.append([i,j])
i, j = ni, nj
else:
j = max(j, nj)
res.append([i,j])
newres = []
for interval in res:
newres.append(interval[1] - interval[0] + 1)
return newres
题目15:56. 合并区间
C++代码如下,
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
int n = intervals.size();
sort(intervals.begin(), intervals.end());
int i = intervals[0][0], j = intervals[0][1];
vector<vector<int>> res;
for (int k = 1; k < n; ++k) {
int ni = intervals[k][0];
int nj = intervals[k][1];
if (ni > j) {
res.emplace_back(vector<int>{i,j});
i = ni;
j = nj;
} else {
j = max(j, nj);
}
}
res.emplace_back(vector<int>{i,j});
return res;
}
};
python3代码如下,
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
n = len(intervals)
res = []
i = intervals[0][0]
j = intervals[0][1]
for k in range(1,n):
ni, nj = intervals[k][0], intervals[k][1]
if ni > j:
res.append([i,j])
i, j = ni, nj
else:
j = max(j, nj)
res.append([i,j])
return res
题目16:738. 单调递增的数字
C++代码如下,
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string s = to_string(n);
n = s.size();
int j = n;
for (int i = n-2; i >= 0; --i) {
if (s[i] > s[i+1]) {
j = i + 1;
s[i] -= 1;
}
}
for (int i = j; i < n; ++i) {
s[i] = '9';
}
return stoi(s);
}
};
python3代码如下,
class Solution:
def monotoneIncreasingDigits(self, n: int) -> int:
s = str(n)
nums = list(s)
n = len(nums)
j = n
for i in range(n-2,-1,-1):
if nums[i] > nums[i+1]:
nums[i] = chr(ord(nums[i]) - 1)
j = i + 1
for i in range(j, n):
nums[i] = '9'
t = "".join(nums)
return int(t)
题目17:968. 监控二叉树
C++代码如下,
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int minCameraCover(TreeNode* root) {
int res = 0;
//结点的状态
//0:表示结点没有被覆盖
//1:表示结点被覆盖,且有照相机
//2:表示结点被覆盖,但没有照相机
function<int(TreeNode*)> dfs =[&] (TreeNode *node) -> int {
//后序遍历,左右根
if (node == nullptr) return 2;
int left = dfs(node->left);
int right = dfs(node->right);
//当前结点处理逻辑
if (left == 2 && right == 2) return 0;
if (left == 0 || right == 0) {
res += 1;
return 1;
}
if (left == 1 || right == 1) return 2;
return -1;
};
if (dfs(root) == 0) res += 1;
return res;
}
};
python3代码如下,
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minCameraCover(self, root: Optional[TreeNode]) -> int:
res = 0
#结点的状态
#0:该结点未被覆盖
#1:该结点被覆盖,且有照相机
#2:该结点被覆盖,但没有照相机
def dfs(node: TreeNode) -> int:
nonlocal res
#后序遍历,左右根
if node is None:
return 2
left = dfs(node.left)
right = dfs(node.right)
#处理逻辑
if left == 2 and right == 2:
return 0
if left == 0 or right == 0:
res += 1
return 1
if left == 1 or right == 1:
return 2
return -1
if dfs(root) == 0:
res += 1
return res