Task4


题目要求
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
思路一
记录高点低点,当高点后一天的价格小于高点,那么将之前的抛出,重新定位高点和低点,记得最后一次记录操作要变现

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices:
            return 0
        low = high = prices[0]
        profit = 0
        for i in prices[1:]:####low遍历每一个元素,找low之后的元素,比low大就标记high,用high-low记录买入买出。
            if high <= i:
                high = i
            else:
                profit += high - low
                low = high = i
        return profit + high - low
思路二
不考虑高点低点,只要相邻的两天有收益,那就是我的,是一种将收益分散到相邻两天进行累加的方式,其结果和高低点变动时算收益是一样的。例如:[7, 1, 5, 6] 第二天买入,第四天卖出,收益最大(6-1),所以一般人可能会想,怎么判断不是第三天就卖出了呢? 这里就把问题复杂化了,根据题目的意思,当天卖出以后,当天还可以买入,所以其实可以第三天卖出,第三天买入,第四天又卖出((5-1+6-5=== 6 - 1)。所以算法可以直接简化为只要今天比昨天大,就卖出。


class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices:
            return 0
        profit = 0
        for i in range(1, len(prices)):
            p = prices[i] - prices[i-1]
            if p > 0:
                profit += p
        return profit
在 C# 中使用 `Task.Run` 并行执行多个任务时,输出顺序混乱通常是由并发执行机制和共享资源访问竞争导致的。当多个任务同时运行并尝试向控制台输出信息时,由于操作系统调度线程的不确定性,可能导致输出内容交错或重复显示特定任务名称[^1]。 ### 输出顺序混乱的原因 1. **任务并行性** `Task.Run` 会将任务提交到线程池中异步执行,这意味着多个任务可能在同一时间段内交替运行。操作系统根据可用资源动态分配线程,因此无法保证任务的执行顺序[^2]。 2. **闭包捕获问题** 在循环中创建任务时,如果直接使用循环变量 `i`,可能会导致所有任务引用同一个变量实例,最终输出错误的索引值。例如,在以下代码中: ```csharp for (int i = 0; i < 3; i++) { tasks[i] = Task.Run(() => DoWork($"Task {i + 1}")); } ``` 所有任务可能都引用了 `i` 的最终值(如 `3`),从而导致输出为 “Task 4” 三3. **控制台输出竞争** 控制台是共享资源,多个任务同时调用 `Console.WriteLine` 可能导致输出内容交错。例如,一个任务打印了部分字符串后被抢占,另一个任务开始输出,最终造成信息混杂。 --- ### 示例代码分析 以下为原始代码片段: ```csharp public static void Main() { Task[] tasks = new Task[3]; for (int i = 0; i < 3; i++) { tasks[i] = Task.Run(() => DoWork($"Task {i + 1}")); } Console.WriteLine("All tasks completed. Proceeding to next step."); } private static void DoWork(string taskName) { Console.WriteLine($"{taskName} is starting..."); Task.Delay(1000).Wait(); Console.WriteLine($"{taskName} is completed."); } ``` 此代码中存在两个主要问题: - **闭包捕获问题**:在 `for` 循环中直接使用 `i`,导致所有任务可能读取相同的 `i` 值。 - **未等待任务完成**:主线程未等待所有任务完成就继续执行后续逻辑,可能导致部分任务尚未执行完毕,程序就已结束。 --- ### 改进方案 #### 修复闭包捕获问题 将循环变量复制到局部变量中再传递给任务体: ```csharp for (int i = 0; i < 3; i++) { int taskId = i; tasks[taskId] = Task.Run(() => DoWork($"Task {taskId + 1}")); } ``` #### 等待所有任务完成 使用 `Task.WaitAll` 确保主线程等待所有任务完成后才继续执行: ```csharp Task.WaitAll(tasks); Console.WriteLine("All tasks completed. Proceeding to next step."); ``` 或者使用 `async/await` 实现更清晰的异步等待: ```csharp public static async Task Main() { Task[] tasks = new Task[3]; for (int i = 0; i < 3; i++) { int taskId = i; tasks[taskId] = Task.Run(() => DoWork($"Task {taskId + 1}")); } await Task.WhenAll(tasks); Console.WriteLine("All tasks completed. Proceeding to next step."); } ``` --- ### 同步与异步等待的区别 - `Task.WaitAll` 是阻塞方式,适用于非异步上下文,但可能导致主线程阻塞。 - `await Task.WhenAll` 是非阻塞方式,更适合 UI 应用或 Web 应用中保持主线程响应性[^1]。 --- ### 控制台输出同步化 若希望避免输出内容交错,可使用锁机制确保一只有一个任务写入控制台: ```csharp private static readonly object lockObj = new object(); private static void DoWork(string taskName) { lock (lockObj) { Console.WriteLine($"{taskName} is starting..."); } Task.Delay(1000).Wait(); lock (lockObj) { Console.WriteLine($"{taskName} is completed."); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值