[贪心算法]买卖股票的最佳时机 && 买卖股票的最佳时机Ⅱ && K次取反后最大化的数组和 && 按身高排序 && 优势洗牌(田忌赛马)

1.买卖股票的最佳时机

暴力解法就是两层循环,找出两个差值最大的即可。 优化:在找最小的时候不用每次都循环一遍,只要在i向后走的时候,每次记录一下最小的值即可

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        int ret=0;
        for(int i=0,prevMin=INT_MAX;i<n;i++)//i是卖的那一天
        {
            //1.先更新结果
            ret=max(ret,prices[i]-prevMin);
            //2.更新最小值
            prevMin=min(prices[i],prevMin);
        }
        return ret;
    }
};

2.买卖股票的最佳时机Ⅱ


只需要在每次上升到最高点的时候卖掉即可,这样+起来的总和就是最高利润;

  • 当prices[j+1]>prices[j] 时,就让j++
  • 走到prices[j+1]<prices[j]就让,i++,j=i 继续向后寻找,直到出现prices[j+1]>prices[j]
cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        int ret=0;
        for(int i=0;i<n;i++)
        {
            int j=i;
            while(j+1<n && prices[j+1]>prices[j])
                j++;
            ret+=prices[j]-prices[i];

            i=j;
        }
        return ret;
    }
};

3.K次取反后最大化的数组

我们设m是整个数组中负数的个数,那么就根据m和k的大小进行分类讨论

  • m>k (先排序)反转前k个数,再相加
  • m==k 把所有的数都当成正数加起来
  • m<k
复制代码
     1.当k-m是偶数时,就和m==k情况相同
复制代码
       2.当k-m是奇数时,把绝对值最小的那个数变成负数即可
cpp 复制代码
class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        int m = 0;
        int minElm = INT_MAX;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] < 0)
                m++;
            minElm = min(minElm, abs(nums[i]));
        }
        int ret = 0;
        // 分类讨论
        if (m > k) {
            sort(nums.begin(), nums.end());
            for (int i = 0; i < k; i++) {
                ret += abs(nums[i]);
            }
            for (int i = k; i < nums.size(); i++) {
                ret += nums[i];
            }
        } else if (m == k) {
            for (int i = 0; i < nums.size(); i++)
                ret += abs(nums[i]);
        } else {
            if ((k - m) % 2 == 0) // 偶数
            {
                for (int i = 0; i < nums.size(); i++)
                    ret += abs(nums[i]);
            }
            else
            {
                for (int i = 0; i < nums.size(); i++)
                    ret += abs(nums[i]);
                ret=ret-2*minElm;
            }
        }
        return ret;
    }
};

4.按身高排序

  1. 创建一个下标数组
  2. 仅需对下标数组排序(根据身高进行排序规则的改变)
  3. 根据下标找到对应的字符串
cpp 复制代码
class Solution {
public:
    vector<string> sortPeople(vector<string>& names, vector<int>& heights) {
        //创建一个数组下标
        int n=heights.size();
        vector<int> v(n);
        for(int i=0;i<n;i++)
            v[i]=i;
        //重写sort的比较方法
        sort(v.begin(),v.end(),[&](int i,int j)
        {
            return heights[i]>heights[j];
        });
        //通过下表找到响应的字符串
        vector<string> ret;
        for(int i:v)
        {
            ret.push_back(names[i]);
        }
        return ret;
    }
};

优势洗牌(田忌赛马)

排序(贪心)

  1. 最差的能比过就直接比
  2. 比不过就去跟对面最大的比,废物利用最大化

步骤:

先对两个数组排序,然后用贪心的思想去排序,这样出来的结果和题目的实例是不一样的;

原因就在于题目的nums2没有排序,所以我们就要用到身高那一题的思想用下标数组 来解决,

创建一个index数组,数组的排序规则就是比较nums2中的大小,然后再index数组中创建一个left和right用来记录最大值和最小值

cpp 复制代码
class Solution {
public:
    vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
        int n=nums2.size();
        vector<int> ret(n);//存放结果
        vector<int> index(n);//下标数组
        for(int i=0;i<n;i++)
        {
            index[i]=i;
        }
        sort(nums1.begin(),nums1.end());
        //下标数组排序
        sort(index.begin(),index.end(),
            [&](int p1,int p2){
                return nums2[p1]<nums2[p2];
            });
        //记录index的左右两边
        int left=0,right=n-1;
        for(int i=0;i<n;i++)
        {
            //贪心:比得过就比,比不过就跟最大的比
            if(nums1[i]>nums2[index[left]])
            {
                ret[index[left++]]=nums1[i];
            }
            else
            {
                ret[index[right--]]=nums1[i];
            }
        }
        return ret;
    }
};
相关推荐
20130924162728 分钟前
1968年 Hart, Nilsson, Raphael 《最小成本路径启发式确定的形式基础》A* 算法深度研究报告
人工智能·算法
如何原谅奋力过但无声32 分钟前
【力扣-Python-滑动窗口经典题】567.字符串的排列 | 424.替换后的最长重复字符 | 76.最小覆盖子串
算法·leetcode
玄冥剑尊1 小时前
贪心算法进阶
算法·贪心算法
玄冥剑尊2 小时前
贪心算法深化 I
算法·贪心算法
52Hz1182 小时前
力扣73.矩阵置零、54.螺旋矩阵、48.旋转图像
python·算法·leetcode·矩阵
BHXDML2 小时前
第一章:线性回归& 逻辑回归
算法·逻辑回归·线性回归
iAkuya2 小时前
(leetcode)力扣100 二叉搜索树种第K小的元素(中序遍历||记录子树的节点数)
算法·leetcode·职场和发展
Remember_9933 小时前
【LeetCode精选算法】滑动窗口专题二
java·开发语言·数据结构·算法·leetcode
Gorgous—l4 小时前
数据结构算法学习:LeetCode热题100-动态规划篇(下)(单词拆分、最长递增子序列、乘积最大子数组、分割等和子集、最长有效括号)
数据结构·学习·算法
北京地铁1号线5 小时前
2.3 相似度算法详解:Cosine Similarity 与 Euclidean Distance
算法·余弦相似度