LeetCode - 解题笔记 - 135 - Candy

Solution 1

将整个问题解构,实际上就是一种贪心策略。

  1. 当前位置的取值只跟前后两个邻居相关
  2. 绝对升序列下,当前位置的糖果数目才会增加

基于这两个解构项,我们可以确定,任何一个局部最小值(允许相等)都可以只给1个糖果,那么相当于我们需要只找到一个个小山,每个山的左右两个端点(局部最小)一定是1,然后内部按照升序列递增计算,峰顶取最大结果的一侧。

【参考官方】官方题解形式化成双指针的设计,左右各遍历一次以寻找升序列,且每个位置初始化为1,因此可以直接更新结果,只是在从右往左遍历时,每个点的取值取决的二者方案的最大。

  • 时间复杂度: O ( N ) O(N) O(N),其中 N N N为输入长度,三次线性遍历
  • 空间复杂度: O ( N ) O(N) O(N),其中 N N N为输入长度,保存分配临时结果
class Solution {
public:
    int candy(vector<int>& ratings) {
        int num = ratings.size();
        vector<int> candy(num, 1);
        
        // 从左到右,检查升序列
        for (int i = 1; i < num; ++i) {
            if (ratings[i] > ratings[i - 1]) {
                candy[i] = candy[i - 1] + 1;
            }
        }
        
        // 从右到左,检查升序列,实际上就是降序列
        for (int i = num - 2; i >=0 ; --i) {
            if (ratings[i] > ratings[i + 1]) {
                // 取两个序列下当前位置取值的最优方案
                candy[i] = max(candy[i], candy[i + 1] + 1);
            }
        }
        
        int ans = accumulate(candy.begin(), candy.end(), 0);
        
        return ans;
    }
};

Solution 2

【参考官方】继续对上一个分析进行简化:由于一个连续的绝对上升序列的糖果分配是一个等差递增序列,那么可以通过序列长度知道这个序列分配结果的总和,因此可以通过对状态的记录简化空间占用。

  1. 对方向的判断,简化成两个方向状态量,用二者的大小映射小山的位置
  2. 使用up和down分别描述小山的两条边
  3. 最后计数时,需要留意最大取值,以及边界情况下虚拟结点的引入
  • 时间复杂度: O ( N ) O(N) O(N),其中 N N N为输入长度,三次线性遍历
  • 空间复杂度: O ( N ) O(N) O(N),仅维护常数个状态量
class Solution {
public:
    int candy(vector<int>& ratings) {
        int ans = 0;
        int up = 0;
        int down = 0;
        int dir = 0;
        
        for (int i = 1; i < ratings.size(); ++i) {
            // 判断方向
            int tempDir = (ratings[i] > ratings[i - 1])? 1: (ratings[i] < ratings[i - 1])? -1: 0;
            
            // 当前位置出现局部最小(允许相等)
            if ((dir > 0 && tempDir == 0) || (dir < 0 && tempDir >= 0)) {
                // 整理当前小山,最高位取两侧最大
                ans += tempSum(up) + tempSum(down) + max(up, down);
                up = 0;
                down = 0;
            }
            
            // 从当前位置开始继续更新
            if (tempDir > 0) {
                // 当前升序
                up++;
            } else if (tempDir < 0) {
                // 当前降序
                down++;
            } else {
                // 平缓,仍然取1,且跳过小山计算
                ans ++;
            }
            
            dir = tempDir;
        }
        
        // 最后结尾情况,虚拟化一个外部的最小结点
        ans += tempSum(up) + tempSum(down) + max(up, down) + 1;
        
        return ans;
    }
    
    int tempSum(int n) {
        return n * (n + 1) / 2;
    }
};

Solution 3

Solution 1的Python实现

class Solution:
    def candy(self, ratings: List[int]) -> int:
        num = len(ratings)
        candy = [1] * num
        
        for i in range(1, num):
            
            if ratings[i] > ratings[i - 1]:
                candy[i] = candy[i - 1] + 1
                
        for i in range(num - 2, -1, -1):
            
            if ratings[i] > ratings[i + 1]:
                candy[i] = max(candy[i], candy[i + 1] + 1)
                
        ans = sum(candy)
        
        return ans

Solution 4

Solution 2的Python实现

class Solution:
    def candy(self, ratings: List[int]) -> int:
        num = len(ratings)
    
        def tempSum(n):
            return n * (n + 1) // 2
        
        ans = 0
        up, down = 0, 0
        D = 0
        
        for i in range (1, num):
            tempDir = 1 if ratings[i] > ratings[i - 1] else -1 if ratings[i] < ratings[i - 1] else 0
            
            if (D > 0 and tempDir == 0) or (D < 0 and tempDir >= 0):
                ans += tempSum(up) + tempSum(down) + max(up, down)
                up, down = 0, 0
                
            if tempDir > 0: up += 1
            elif tempDir < 0: down += 1
            else: ans += 1
                
            D = tempDir
                
        ans += tempSum(up) + tempSum(down) + max(up, down) + 1
    
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值