【Leetcode Sheet】Weekly Practice 10

Leetcode Test

123 买卖股票的最佳时机Ⅲ(10.3)

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

**注意:**你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

提示:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 105

【动态规划】

int maxProfit(int* prices, int pricesSize){
    //buy1: buy once
    //sell1: buy once & sell once
    //buy2: buy twice & sell once
    //sell2: buy twice & sell twice

    //buy1[i] = max(buy1[i-1], -prices[i])
    //sell1[i] = max(sell1[i-1], buy1[i-1]+prices[i])
    //buy2[i] = max(buy2[i], sell1[i]-prices[i])
    //sell2[i] = max(sell2[i], buy2[i-1]+prices[i])

    //buy1[0]=-prices[0] 同一天买
    //sell1[0]=0 同一天买+卖
    //buy2[0]=-princes[0] 同一天买+卖+买
    //sell2[0]=0 同一天买+卖+买+卖

    int buy1=-prices[0],sell1=0;
    int buy2=buy1,sell2=sell1;

    for(int i=1;i<pricesSize;i++){
        buy1=fmax(buy1,-prices[i]);
        sell1=fmax(sell1,buy1+prices[i]);
        buy2=fmax(buy2,sell1-prices[i]);
        sell2=fmax(sell2,buy2+prices[i]);
    }
    return sell2;
}

188 买卖股票的最佳时机Ⅳ(10.4)

给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。

**注意:**你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

提示:

  • 1 <= k <= 100
  • 1 <= prices.length <= 1000
  • 0 <= prices[i] <= 1000

【动态规划】universal version

int maxProfit(int k, int* prices, int pricesSize){
    int n=pricesSize;
    int f[k+2][2];
    //[0]代表sell,[1]代表buy
    memset(f,-0x3f,sizeof(f));

    for(int j=1;j<k+2;j++){
        f[j][0]=0;//先把sell全部赋值为0
    }

    for(int i=0;i<n;i++){
        for(int j=1;j<k+2;j++){
            f[j][0]=fmax(f[j][0],f[j][1]+prices[i]);
            f[j][1]=fmax(f[j][1],f[j-1][0]-prices[i]);
        }
    }

    return f[k+1][0];
}

309 买卖股票的最佳时机含冷冻期(10.5)

给定一个整数数组prices,其中第 prices[i] 表示第 *i* 天的股票价格 。

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

**注意:**你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

提示:

  • 1 <= prices.length <= 5000
  • 0 <= prices[i] <= 1000

【动态规划】

int maxProfit(int* prices, int pricesSize){
    //0:手里有票,今天可以卖
    //1:前一天冻结,今天不能买
    //2:手里没票,今天可以买

    int n=pricesSize;
    int f[n][3];
    f[0][0]=-prices[0];
    f[0][1]=f[0][2]=0;

    for(int i=1;i<n;i++){
        f[i][0]=fmax(f[i-1][0],f[i-1][2]-prices[i]);
        //i-1天有票,或i-1天没票时买了票
        f[i][1]=f[i-1][0]+prices[i];
        //一定是i-1天买了票,所以i天才会冻结
        f[i][2]=fmax(f[i-1][2],f[i-1][1]);
        //i-1天没票,或冻结期刚结束
    }

    return fmax(f[n-1][2],f[n-1][1]);
    //返回最后一天手里没票,或最后一天在冻结期
}

714 买卖股票的最佳时机含手续费(10.6)

给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

**注意:**这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

提示:

  • 1 <= prices.length <= 5 * 104
  • 1 <= prices[i] < 5 * 104
  • 0 <= fee < 5 * 104

【动态规划】

int maxProfit(int* prices, int pricesSize, int fee){
    int n=pricesSize;
    int f[n+1][2];
    memset(f,0,sizeof(f));

    f[0][1]=INT_MIN/2;
    for(int i=0;i<n;i++){
        f[i+1][0]=fmax(f[i][0],f[i][1]+prices[i]-fee);
        f[i+1][1]=fmax(f[i][1],f[i][0]-prices[i]);
    }
    return f[n][0];
}

901 股票价格跨度(10.7)

设计一个算法收集某些股票的每日报价,并返回该股票当日价格的 跨度

当日股票价格的 跨度 被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。

  • 例如,如果未来 7 天股票的价格是 [100,80,60,70,60,75,85],那么股票跨度将是 [1,1,1,2,1,4,6]

实现 StockSpanner 类:

  • StockSpanner() 初始化类对象。
  • int next(int price) 给出今天的股价 price ,返回该股票当日价格的 跨度

提示:

  • 1 <= price <= 105
  • 最多调用 next 方法 104

【单调栈】(这东西还是cpp好用…)

class StockSpanner {
    stack<pair<int, int>> st;
    int cur_day = -1; // 第一个 next 调用算作第 0 天
public:
    StockSpanner() {
        st.emplace(-1, INT_MAX); // 这样无需判断栈为空的情况
    }

    int next(int price) {
        while (price >= st.top().second) {
            st.pop(); // 栈顶数据后面不会再用到了,因为 price 更大
        }
        int ans = ++cur_day - st.top().first;
        st.emplace(cur_day, price);
        return ans;
    }
};

/**
 * Your StockSpanner object will be instantiated and called as such:
 * StockSpanner* obj = new StockSpanner();
 * int param_1 = obj->next(price);
 */

2034 股票价格波动(10.8)

给你一支股票价格的数据流。数据流中每一条记录包含一个 时间戳 和该时间点股票对应的 价格

不巧的是,由于股票市场内在的波动性,股票价格记录可能不是按时间顺序到来的。某些情况下,有的记录可能是错的。如果两个有相同时间戳的记录出现在数据流中,前一条记录视为错误记录,后出现的记录 更正 前一条错误的记录。

请你设计一个算法,实现:

  • 更新 股票在某一时间戳的股票价格,如果有之前同一时间戳的价格,这一操作将 更正 之前的错误价格。
  • 找到当前记录里 最新股票价格最新股票价格 定义为时间戳最晚的股票价格。
  • 找到当前记录里股票的 最高价格
  • 找到当前记录里股票的 最低价格

请你实现 StockPrice 类:

  • StockPrice() 初始化对象,当前无股票价格记录。
  • void update(int timestamp, int price) 在时间点 timestamp 更新股票价格为 price
  • int current() 返回股票 最新价格
  • int maximum() 返回股票 最高价格
  • int minimum() 返回股票 最低价格

提示:

  • 1 <= timestamp, price <= 109
  • updatecurrentmaximumminimum 调用次数不超过 105
  • currentmaximumminimum 被调用时,update 操作 至少 已经被调用过 一次

【hash + 有序集合】

class StockPrice {
    int maxTimestamp;
    unordered_map<int,int> timePriceMap;
    multiset<int> prices;
public:
    StockPrice() {
        this->maxTimestamp=0;
        //初始化对象,当前无股票价格记录
    }
    
    void update(int timestamp, int price) {
        //在时间点 `timestamp` 更新股票价格为 `price`
        maxTimestamp=max(maxTimestamp,timestamp);
        int prevPrice=timePriceMap.count(timestamp) ? timePriceMap[timestamp] : 0;
        //上次的价格
        timePriceMap[timestamp]=price;
        //这次的价格
        if(prevPrice>0){
            //如果有上次的
            auto it=prices.find(prevPrice);
            if(it!=prices.end()){
                prices.erase(it);
            }
        }
        prices.emplace(price);
    }
    
    int current() {
        return timePriceMap[maxTimestamp];
    }
    
    int maximum() {
        return *prices.rbegin();
    }
    
    int minimum() {
        return *prices.begin();
    }
};

/**
 * Your StockPrice object will be instantiated and called as such:
 * StockPrice* obj = new StockPrice();
 * obj->update(timestamp,price);
 * int param_2 = obj->current();
 * int param_3 = obj->maximum();
 * int param_4 = obj->minimum();
 */

2578 最小和分割(10.9)

给你一个正整数 num ,请你将它分割成两个非负整数 num1num2 ,满足:

  • num1num2 直接连起来,得到 num 各数位的一个排列。

    • 换句话说,num1num2 中所有数字出现的次数之和等于 num 中所有数字出现的次数。
  • num1num2 可以包含前导 0 。

请你返回 num1num2 可以得到的和的 最小 值。

提示:

  • 10 <= num <= 10^9

【排序 + 奇偶对】

int cmp(void *a,void *b){
    return *(int*)a-*(int*)b;
}
int splitNum(int num){
    int *split=malloc(sizeof(int)*20);
    int cnt=0;
    while(num>0){
        split[cnt++]=num%10;
        num/=10;
    }
    qsort(split,cnt,sizeof(int),cmp);
    int n1=0,n2=0;
    for(int i=0;i<cnt;i++){
        if(i%2==0){
            n1*=10;
            n1+=split[i];
        }
        else{
            n2*=10;
            n2+=split[i];
        }
    }
    return n1+n2;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MorleyOlsen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值