[日常刷题]leetcode第十二天

本文深入探讨了股票买卖时机的最优算法,包括一次交易和多次交易的最佳策略,以及有效验证字符串是否为回文的算法实现。通过具体案例分析,提供了C++代码示例,帮助读者理解算法原理和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

121. Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.
Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

Solution in C++:

关键点

  • 购入和抛售相对大小

思路

  • 我采取的是暴力的方法,用的冒泡排序的遍历方法,把插值大于0的部分与max进行对比输出。后面也看到了leetcode本身提供的solution中的找极值的算法。思想是min一定是我在prices[i]之前找到的,所以可以直接用来作为减数,得到的最大值即为所求

方法一 暴力

int maxProfit(vector<int>& prices) {
        int max = 0;
        size_t size = prices.size();
        
        for ( int i = 0; i < size; ++i){
            for ( int j = i; j < size; ++j){
                if (prices[i] < prices[j])
                {
                    int tmp = prices[j] - prices[i];
                    max = (max < tmp?tmp:max);
                }
            }
        }
        
        return max;
    }

方法二 遍历一遍,获取后续极小值与极大值

		int min = INT_MAX;
        int max = 0;
        size_t size = prices.size();
        for (int i = 0; i < size; ++i){
            if (prices[i] < min)
                min = prices[i];
            else if (prices[i] - min > max)
                max = prices[i] - min;
        }
        return max;

122. Best Time to Buy and Sell Stock II

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).

Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).
Example 1:

Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
             Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

Solution in C++:
关键点

  • 可以多次抛售,需要顾及前后的影响

思路

  • 相当于三角形问题,两边之和肯定是大于第三边的,所以直接忽略中间点几次的交易肯定是小于进行几次交易的。所以核心点就是我们每次找到相对最小的点和相对大的点进行减法就OK了
int maxProfit(vector<int>& prices) {
        size_t size = prices.size();
        if ( size == 0)
            return 0;
            
        int valley = prices[0];
        int peak = prices[0];
        int max = 0;
        int i = 0;
        
        while (i < size - 1)
        {
            while ( i < size - 1 && prices[i] >= prices[i + 1])
                ++i;
            valley = prices[i];
            while ( i < size - 1 && prices[i] <= prices[i + 1])
                ++i;
            peak = prices[i];
            max += peak - valley;
        }
        return max;
    }

125. Valid Palindrome

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

Note: For the purpose of this problem, we define empty string as valid palindrome.
Example 1:

Input: "A man, a plan, a canal: Panama"
Output: true

Example 2:

Input: "race a car"
Output: false

Solution in C++:
关键点

  • 合法性判断&&前后位置标识移动逻辑

思路

  • 首先是考虑字符串的有效性,然后一头一尾的位置标识遍历字符串,在遍历的过程中如果只有一方的位置标识遇到了非字母及数字的字符就只有该方的位置标识进行挪动,同时判断条件中只返回False的情况,其他运行到最后都是true则返回true
bool isPalindrome(string s) {
        if ( s == "")
            return true;
        
        size_t size = s.size();
        size_t gap = 'a' - 'A';
        for(int i = 0, j = size - 1; i <= j; ++i, --j){
            bool ian = (!isalpha(s[i]) && !isdigit(s[i])); // i为非字母/非数字
            bool jan = (!isalpha(s[j]) && !isdigit(s[j]));
            if (ian && jan)
                continue;
            else if (ian || jan){
                if (ian)
                    ++j;
                else
                    --i;
                continue;
            }
            
            int tmp = abs(s[i] - s[j]);
            if(isalpha(s[i])) // 字母
            {
                if (tmp != gap && tmp != 0)
                    return false;
            } else{
                if (tmp != 0)
                    return false;
            }
        } 
        return true;
    }

小结

今天主要在抛售票的题目中学到了画图去解决问题的思路,以及这种求值大小问题需要考虑一些数学知识。在合法回文中主要学习到的是对于逻辑的正向表达((!isalpha(s[i]) && !isdigit(s[i]))),不要反反的逻辑让自己晕了。

知识点

  • 数学问题
  • 字符处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值