LeetCode 1262. 可被三整除的最大和

这篇具有很好参考价值的文章主要介绍了LeetCode 1262. 可被三整除的最大和。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【LetMeFly】1262.可被三整除的最大和:时间O(n)空间O(1)

力扣题目链接:https://leetcode.cn/problems/greatest-sum-divisible-by-three/

给你一个整数数组 nums,请你找出并返回能被三整除的元素最大和。

     

    示例 1:

    输入:nums = [3,6,5,1,8]
    输出:18
    解释:选出数字 3, 6, 1 和 8,它们的和是 18(可被 3 整除的最大和)。

    示例 2:

    输入:nums = [4]
    输出:0
    解释:4 不能被 3 整除,所以无法选出数字,返回 0。
    

    示例 3:

    输入:nums = [1,2,3,4,4]
    输出:12
    解释:选出数字 1, 3, 4 以及 4,它们的和是 12(可被 3 整除的最大和)。
    

     

    提示:

    • 1 <= nums.length <= 4 * 10^4
    • 1 <= nums[i] <= 10^4

    方法一:数学 + 同余

    一个数对3取模,只有0、1、2这三种情况。

    我们只需要对nums中所有数求和(cnt)并对3取模:

    • 如果取模结果为0,直接返回cnt
    • 如果取模结果为1,cnt减去一个最小的模3为1的数 或 减去两个最小的模3为2的数 并返回(若无充足的数可供减去,则返回0)
    • 如果取模结果为1,cnt减去一个最小的模3为2的数 或 减去两个最小的模3为1的数 并返回

    上述表达中,“两个最小的数”意思为最小的和第二小的两个数。

    那么,怎么确定模3为1的所有的数中,最小的一个或最小的两个呢?

    最简单的方法就是排序。但是排序需要消耗O(n)的时间和O(log n)的空间,时空消耗太大了

    有没有什么时间O(n)空间O(1)的方法呢?当然有。

    我们只需要写一个类,类中有三个变量:min1、min2、num。

    其中min1代表最小的数,min2代表第二小的数,num代表min1和min2两个变量中有效变量的数量。

    每次遇到一个模3为1的数,我们只需要调用类中的更新函数,遍历结束后即可获得最小值和第二小值。

    • 时间复杂度 O ( l e n ( n u m s ) ) O(len(nums)) O(len(nums))
    • 空间复杂度 O ( 1 ) O(1) O(1)

    AC代码

    C++
    class Min2 {  // 最小的两个数(范围1-10^4)
    private:
        int min1, min2;
        int num;
    public:
        Min2() {
            min1 = min2 = num = 0;
        }
    
        void update(int n) {
            if (!num) {
                min1 = n;
                num = 1;
            }
            else if (num == 1) {
                min2 = n;
                num = 2;
                if (min1 > min2) {
                    swap(min1, min2);
                }
            }
            else {
                if (n < min1) {
                    min2 = min1;
                    min1 = n;
                }
                else if (n < min2) {
                    min2 = n;
                }
            }
        }
    
        int getMin1() {
            return min1;
        }
    
        int getMin2() {
            return min2;
        }
    
        int getMinNum() {
            return num;
        }
    };
    
    class Solution {
    public:
        int maxSumDivThree(vector<int>& nums) {
            Min2 mod1, mod2;
            int cnt = 0;
            for (int t : nums) {
                cnt += t;
                if (t % 3 == 1) {
                    mod1.update(t);
                }
                else if (t % 3 == 2) {
                    mod2.update(t);
                }
            }
            if (cnt % 3 == 0) {
                return cnt;
            }
            else if (cnt % 3 == 1) {  // 减去一个模为1的或两个模为2的
                if (mod1.getMinNum() < 1 && mod2.getMinNum() < 2) {
                    return 0;
                }
                int ans = 0;
                if (mod1.getMinNum()) {
                    ans = max(ans, cnt - mod1.getMin1());
                }
                if (mod2.getMinNum() >= 2) {
                    ans = max(ans, cnt - mod2.getMin1() - mod2.getMin2());
                }
                return ans;
            }
            else {  // 减去一个模为2的或两个模为1的
                if (mod2.getMinNum() < 1 && mod1.getMinNum() < 2) {
                    return 0;
                }
                int ans = 0;
                if (mod2.getMinNum()) {
                    ans = max(ans, cnt - mod2.getMin1());
                }
                if (mod1.getMinNum() >= 2) {
                    ans = max(ans, cnt - mod1.getMin1() - mod1.getMin2());
                }
                return ans;
            }
        }
    };
    
    Python
    # from typing import List
    
    
    class Min2:
        min1 = 0
        min2 = 0
        num = 0
    
        def update(self, n: int) -> None:
            if not self.num:
                self.min1 = n
                self.num = 1
            elif self.num == 1:
                self.min2 = n
                self.num = 2
                if self.min1 > self.min2:
                    self.min1, self.min2 = self.min2, self.min1
            else:
                if n < self.min1:
                    self.min2 = self.min1
                    self.min1 = n
                elif n < self.min2:
                    self.min2 = n
        
        def getMin1(self) -> int:
            return self.min1
        
        def getMin2(self) -> int:
            return self.min2
        
        def getMinNum(self) -> int:
            return self.num
    
    
    class Solution:
        def maxSumDivThree(self, nums: List[int]) -> int:
            mod1, mod2 = Min2(), Min2()
            cnt = 0
            for t in nums:
                cnt += t
                if t % 3 == 1:
                    mod1.update(t)
                elif t % 3 == 2:
                    mod2.update(t)
            if cnt % 3 == 0:
                return cnt
            elif cnt % 3 == 1:
                ans = 0
                if mod1.getMinNum():
                    ans = max(ans, cnt - mod1.getMin1())
                if mod2.getMinNum() >= 2:
                    ans = max(ans, cnt - mod2.getMin1() - mod2.getMin2())
                return ans
            else:
                ans = 0
                if mod2.getMinNum():
                    ans = max(ans, cnt - mod2.getMin1())
                if mod1.getMinNum() >= 2:
                    ans = max(ans, cnt - mod1.getMin1() - mod1.getMin2())
                return ans
    

    同步发文于CSDN,原创不易,转载请附上原文链接哦~
    Tisfy:https://letmefly.blog.csdn.net/article/details/131290984文章来源地址https://www.toymoban.com/news/detail-491408.html

    到了这里,关于LeetCode 1262. 可被三整除的最大和的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

    领支付宝红包 赞助服务器费用

    相关文章

    • 【1015. 可被 K 整除的最小整数】

      来源:力扣(LeetCode) 描述: 给定正整数 k ,你需要找出可以被 k 整除的、仅包含数字 1 的最 小 正整数 n 的长度。 返回 n 的长度。如果不存在这样的 n ,就返回 -1 。 注意: n 不符合 64 位带符号整数。 示例 1: 示例 2: 示例 3: 提示: 1 = k = 10 5 方法:遍历 思路与算法 题

      2024年02月03日
      浏览(61)
    • 和可被K整除的子数组(Java详解)

      目录 一、题目描述 二、题解 思路分析 具体实现 完整代码 给定一个整数数组  nums  和一个整数  k  ,返回其中元素之和可被  k  整除的(连续、非空)  子数组  的数目。 子数组  是数组的  连续  部分。 示例: 输入:nums = [4,5,0,-2,-3,1],k = 5 输出:7 输入:nums = [ 5 ],

      2024年02月01日
      浏览(27)
    • 【数字IC手撕代码】Verilog模三检测器(判断输入序列能否被三整除)|题目|原理|设计|仿真

      芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区 联合力荐 !近500篇 数字IC精品文章收录 ! 【数字IC精品文章收录】学习路线·基础知识·总线·脚本语言·芯片求职·EDA工具·低功耗设计Verilog·STA·设计·验证·FPGA·架构·AMBA·书籍 本系列旨在提

      2024年02月16日
      浏览(27)
    • 【每日一题Day199】LC1010总持续时间可被 60 整除的歌曲 | 哈希表

      总持续时间可被 60 整除的歌曲【LC1010】 在歌曲列表中,第 i 首歌曲的持续时间为 time[i] 秒。 返回其总持续时间(以秒为单位)可被 60 整除的歌曲对的数量。形式上,我们希望下标数字 i 和 j 满足 i j 且有 (time[i] + time[j]) % 60 == 0 。 思路 由于需要求两首歌的总时间可被60整除

      2024年02月03日
      浏览(32)
    • [Algorithm][前缀和][和为K的子数组][和可被K整除的子数组][连续数组][矩阵区域和]详细讲解

      和为 K 的子数组 分析 :因为有 负数 的存在 无法使用\\\" 双指针 \\\"优化,因为 区间求和不具备单调性 可能已经找到前缀和为k的子数组了,但是后面仍然可能会有更长的和为k的子数组存在 思路 :前缀和 + 哈希表 前缀和 : 以 i 位置为结尾 的所有的子数组 将问题转化为 :在

      2024年04月28日
      浏览(26)
    • 算法——前缀和之除自身以外数组的乘积、和为K的子数组、和可被K整除的子数组、连续数组、矩阵区域和

      这几道题对于我们前面讲过的一维、二维前缀和进行了运用,包含了面对特殊情况的反操作 目录 4.除自身以外数组的乘积 4.1解析 4.2题解 5.和为K的子数组 5.1解析 5.2题解 6.和可被K整除的子数组 6.1解析 6.2题解 7.连续数组 7.1题解 7.2题解 8.矩阵区域和 8.1解析 8.2题解 4.除自身以外

      2024年04月14日
      浏览(32)
    • 力扣日记1262

      LeetCode 1262. 可被三整除的最大和 数组中取数,使得和可以整出3且最大,每个数最多选一次 看数据量,复杂度可以到O(nlogn)往上 1 = nums.length = 4 * 10^4 1 = nums[i] = 10^4 思考一下怎么选数, 先想贪心。看出来这个题的答案是需要选数的组合,贪心不出来。 想动态规划。 对于下标

      2024年02月11日
      浏览(26)
    • 【Leetcode】179. 最大数

      给定一组非负整数 nums ,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。 注意 :输出结果可能非常大,所以你需要返回一个字符串而不是整数。 示例1: 示例2: 提示: 1 = nums.length = 100 0 = nums[i] = 10 9

      2024年02月07日
      浏览(28)
    • 【LeetCode】85.最大矩形

      给定一个仅包含  0  和  1  、大小为  rows x cols  的二维二进制矩阵,找出只包含  1  的最大矩形,并返回其面积。 示例 1: 示例 2: 示例 3: 示例 4: 示例 5: 提示: rows == matrix.length cols == matrix[0].length 1 = row, cols = 200 matrix[i][j]  为  \\\'0\\\'  或  \\\'1\\\' 这题是建立在「84.柱形图

      2024年02月10日
      浏览(28)
    • LeetCode 670. 最大交换

      目录 一、题目 1、题目描述 2、接口描述 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 1、题目描述 给定一个非负整数,你 至多 可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 2、接口描述 3、原题链接 670. 最大交换 1、思路分析 贪心的考

      2024年01月23日
      浏览(45)

    觉得文章有用就打赏一下文章作者

    支付宝扫一扫打赏

    博客赞助

    微信扫一扫打赏

    请作者喝杯咖啡吧~博客赞助

    支付宝扫一扫领取红包,优惠每天领

    二维码1

    领取红包

    二维码2

    领红包