LeetCode 1363. 形成三的最大倍数

LeetCode 1363. 形成三的最大倍数

题目来源

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-multiple-of-three/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目描述

给你一个整数数组 digits,你可以通过按任意顺序连接其中某些数字来形成 3 的倍数,请你返回所能得到的最大的 3 的倍数。
由于答案可能不在整数数据类型范围内,请以字符串形式返回答案。
如果无法得到答案,请返回一个空字符串。

示例 1:

输入:digits = [8,1,9]
输出:"981"

示例 2:

输入:digits = [8,6,7,1,0]
输出:"8760"

示例 3:

输入:digits = [1]
输出:""

示例 4:

输入:digits = [0,0,0,0,0,0]
输出:"0"

提示:

1 <= digits.length <= 10^4
0 <= digits[i] <= 9
返回的结果不应包含不必要的前导零。

思路:

首先有一个规律:如果一个数的每一位之和是3的倍数,那个这个数可以被3整除。
假设整个数组之和是3的倍数:

①如果要得到的最大的 3 的倍数,那么要得到这个最大的3的倍数,可以对数组进行排序,最后按顺序输出这个数组即可。例如如果是从小到大排序,那么倒序输出这个数组就是最大的3的倍数。

接下来要解决的问题是如果整个数组之和不是3的倍数:

假设数组之和是sum,remainder = sum%3 != 0,可以考虑到remainder = 1 或者remainder=2。

②如果remainder=1,那么我们需要删除一个最小的且余3为1的即可、或者删除两个最小的且余3为2的数字即可。

③如果remainder=2,那么我们需要删除一个最小的且余3为2的即可、或者删除两个最小的且余3为1的数字即可。

代码如下:

public String largestMultipleOfThree(int[] digits) {
    // 对数组求和
    int sum = 0;
    for (int i : digits) {
        sum += i;
    }
    // 情况①,倒序返回数组即可
    if (sum % 3 == 0) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = digits.length - 1; i >= 0; i--) {
            stringBuilder.append(digits[i]);
        }
        return stringBuilder.toString();
    }
    // 从小到大排序
    Arrays.sort(digits);
    int remainder = sum % 3;

    // 情况②
    if (remainder == 1) {
        int[] rem_2 = new int[2];
        rem_2[0] = -1;
        rem_2[1] = -1;
        // 遍历整个数组
        for (int i = 0; i < digits.length; i++) {
            // 情况②中的第一种情况。如果找到一个数字余数是1,删除这个数字即可
            if (digits[i] % 3 == 1) {
                return removeAndPrintResult(digits, i, -1);
            }
            // 情况②中的第二种情况。如果这个数字余数是2,记录下来,如果找到了两个余数是2的数字,删除这两个数字即可
            if (digits[i] % 3 == 2) {
                // 保存第一个余数是2的数字
                if (rem_2[0] == -1) {
                    rem_2[0] = i;
                }
                // 保存第二个余数是2的数字
                else if (rem_2[1] == -1) {
                    rem_2[1] = i;
                }
            }
        }
        // 如果找到了两个余数是2的数字,删除这俩数组就是答案
        if (rem_2[0] != -1 &&
                rem_2[1] != -1) {
            return removeAndPrintResult(digits, rem_2[0],
                    rem_2[1]);
        }
    }
    // 情况③。如果余数是2
    else if (remainder == 2) {
        int[] rem_1 = new int[2];
        rem_1[0] = -1;
        rem_1[1] = -1;
        // 遍历数组
        for (int i = 0; i < digits.length; i++) {
            // 情况③中的第一种情况。找到一个余数是2的数字,删除即可
            if (digits[i] % 3 == 2) {
                return removeAndPrintResult(digits, i, -1);
            }
            // 情况③中的第二种。尝试寻找两个余数是1的数组,删掉这俩数组也可以
            if (digits[i] % 3 == 1) {
                if (rem_1[0] == -1) {
                    rem_1[0] = i;
                } else if (rem_1[1] == -1) {
                    rem_1[1] = i;
                }
            }
        }
        if (rem_1[0] != -1 &&
                rem_1[1] != -1) {
            return removeAndPrintResult(digits, rem_1[0],
                    rem_1[1]);
        }
    }
    // 其余情况没有答案
    return "";
}
// 删除指定位置的数字构建字符串。
private String removeAndPrintResult(int[] digits,
                                    int ind1, int ind2) {
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = digits.length - 1; i >= 0; i--) {
        if (i != ind1 && i != ind2) {
            stringBuilder.append(digits[i]);
        }
    }
    return stringBuilder.toString();
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值