1. 分配饼干 难度:easy Leetcode题号:455
题目描述:
思路:贪心思想,即将饼干大小和孩子的胃口大小分别排序,将较小的饼干优先分配给胃口较小的孩子,这样才能用较大的饼干尽可能去满足胃口较大的孩子
代码如下:
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int res = 0;
int i = 0 , j = 0;
while( i < g.size() && j < s.size()){
if(s[j] >= g[i]){
res++;//满足了一个孩子
i++;
}
j++;
}
return res;
}
};
2. 无重叠区间 难度:medium Leetcode题目号:435
题目描述:
思路:
要求可去掉的区间的最小值,可先求出无重叠区间个数的最大值unoverlap_interval,然后用总区间个数减去unoverlap_interval,
即为所求
无重叠区间最大个数可用贪心算法进行求解,即:
先按区间末尾值对区间进行升序排序,当区间末尾值相同时,优先选择区间长度短的,即起始值大的;这样就能保证之后留有更多的空间去容纳尽可能多的区间,之后放置区间时,选择和前一个被选中的区间不重叠的
C++代码如下:
class Solution {
public:
static bool cmp(vector<int> &a, vector<int> &b){
if(a[1]<b[1]){
return true;
} else if(a[1]==b[1]){
return a[0]>b[0];
}
return false;
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if(intervals.size()==0){
return 0;
}
sort(intervals.begin(),intervals.end(),cmp);//根据区间末尾进行排序
int unoverlap_interval=1;//未重叠的最大区间数,先把排序后的第一个区间记入
int last=intervals[0][1];//未重叠的上个区间的末尾
for(int i=1;i<intervals.size();i++){
if(intervals[i][0]>=last){
unoverlap_interval++;
last=intervals[i][1];
}
}
int res=intervals.size()-unoverlap_interval;//所有区间数目减去未重叠区间最大数目为答案
return res;
}
};
3. 用最少数量的箭引爆气球 难度:medium Leetcode题号:452
题目描述:
思路:
此题与上一题目几乎一样,区别就在于此题求的就是不重叠区间的数目,且[1,2]与[2,3]这种算作是重叠的区间(因为一支箭可以将二者同时引爆)
代码如下:
bool cmp(vector<int> &a, vector<int> &b){
return a[1]<b[1] || (a[1]==b[1] && a[0]>b[0]);
}
class Solution {
public:
int findMinArrowShots(vector<vector<int>>& points) {
if(points.size() == 0){
return 0;
}
sort(points.begin(), points.end(), cmp);
int res = 1;//不重叠区间的个数
int last = points[0][1];
for(int i = 0; i < points.size(); i++){
if(points[i][0] > last){
res++;
last = points[i][1];
}
}
return res;
}
};
4. 根据身高重建队列 难度:medium Leetcode题号:406
题目描述:
主要突破口:当一群人的身高都一致时,他们应站在的位置就是k值,比如[5,0],[5,1]和[5,2]应依次排列
思路:首先将人群按照身高h进行降序排列,再按前面大于等于自己身高的人数k进行升序排列
先将身高较高且身高一致的人按照k值去安排位置,之后的身高一致的一批人也按照k值去插入其中,由于插入的人的身高总是比原来已安排好的人的身高矮,故插入后不会影响往后挪一个位置的那个人k值与顺序的对应关系
代码如下:
bool cmp(vector<int> &a, vector<int> &b){
return a[0]>b[0] || (a[0]==b[0] && a[1]<b[1]);
}
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), cmp);
vector<vector<int>> ans;
for(int i=0;i<people.size();i++){
ans.insert(ans.begin()+people[i][1], {people[i][0], people[i][1]});
}
return ans;
}
};
5. 买卖股票的最佳时机 难度:easy Leetcode题号:121
题目描述:
思路:记录前面几天的最小价格,每到新的一天都算一下今天卖出的利润,比较一下,若比之前的利润大就更新一下利润,最后得到的就是最大利润
代码:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()==0){
return 0;
}
int n=prices.size();
int Min=INT_MAX;
int ans=0;//利润
for(int i=0;i<n;i++){
if(prices[i]<Min){
Min=prices[i];
} else{
ans=max(ans,prices[i]-Min);//今天卖出是不是比之前的最大利润大
}
}
return ans;
}
};
6. 买卖股票的最佳时机II 难度:easy Leetcode题号:122
题目描述:
思路:
贪心:比如a<x<b,由于有b-a=(b-x)+(x-a),故只要后一天比前一天价格高,就将股票卖出,最后得到的一定是最大利润
C++代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int ans = 0;
for(int i=1;i<prices.size();i++){
if(prices[i]>prices[i-1]){
ans += prices[i]-prices[i-1];
}
}
return ans;
}
};
7. 种花问题 难度:easy Leetcode题号:605
题目描述:
思路:设置一个计数器count,记录还能种花的位置的最大数量,当其前后位置都没有花时(第一个位置和最后一个位置需单独考虑),就种一朵花,若最后count>=n,则表明还可以种上n朵花,否则不能
代码:
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int count = 0;
int len = flowerbed.size();
for(int i = 0; i < len && count <= n; i++){
if(flowerbed[i] == 1){
continue;
}
int pre = i == 0 ? 0 : flowerbed[i-1];
int next = i == len - 1 ? 0 : flowerbed[i+1];
if(pre == 0 && next == 0){
count++;
flowerbed[i] = 1;
}
}
return count >= n;
}
};
8. 判断子序列 难度:easy Leetcode题号:392
题目描述:
思路:双指针+贪心,i指向s串,j指向t串,只考虑s[i]和t[j]是否相等,若s[i]==t[j],两者同时动,否则只有j动,只要能在后面找到它就可以
代码:
class Solution {
public:
bool isSubsequence(string s, string t) {
int i = 0, j = 0;
int count = 0;
while(i < s.size() && j < t.size()){
if(s[i] == t[j]){
count++;
i++;
}
j++;
}
return count == s.size();
}
};
9. 非递减数列 难度:easy Leetcode题号:665
题目描述:
思路:
当数组中出现nums[i] < nums[i-1] 的情况时,应考虑修改哪个数,能够使得i之前位置的数组成一个非递减数列,并不影响后续操作(即贪心,只考虑眼下最优的),显然应该令nums[i-1] = nums[i],因为若令nums[i] = nums[i-1],则i位置的值变大了,有可能比nums[i+1]大,而影响了后续操作。还有一种特殊的情况:nums[i] < nums[i-2],这种情况下若令nums[i-1] = nums[i],则仍不满足非递减数列,故这时只能令nums[i] = nums[i-1]
代码如下:
class Solution {
public:
bool checkPossibility(vector<int>& nums) {
int count = 0;
for(int i = 1; i < nums.size() && count <= 1; i++){
if(nums[i] >= nums[i-1]){
continue;
}
count++;
if(i-2 >= 0 && nums[i] < nums[i-2]){
nums[i] = nums[i-1];
} else{
nums[i-1] = nums[i];
}
}
return count <= 1;
}
};
10. 最大子序列和 难度:easy Leetcode题号: 53
题目描述:
思路:
使用一个pre_sum变量记录到当前数的最大子序和,一个max_sum变量记录真正的最大子序和,若考虑nums[i]和pre_sum+nums[i]的大小,去二者的较大值,然后比较pre_sum和max_sum的值,更新max_sum的值
代码如下:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==0){
return 0;
}
int n=nums.size();
int pre_sum = nums[0];
int max_sum = pre_sum;
for(int i=1;i<n;i++){
pre_sum = pre_sum > 0 ? pre_sum + nums[i] : nums[i];
max_sum = max(max_sum, pre_sum);
}
return max_sum;
}
};
11. 划分字母区间 难度:medium Leetcode题号:763
题目描述:
代码:
class Solution {
public:
vector<int> partitionLabels(string S) {
vector<int> res;
map<char,int> Map;
int start = 0, end = 0;
for(int i = 0; i < S.size(); i++){
Map[S[i]] = i; //记录每个字母的最大下标
}
for(int i = 0 ; i < S.size(); i++){
end = max(end, Map[S[i]]);//若当前字母的最大下标大于end,则将end拓展
if(i == end){
res.push_back(end - start + 1);
start = i + 1;//开始搜索下一个片段
}
}
return res;
}
};