LeetCode 1363. 形成三的最大倍数
题目描述
思路分析
解法一:计数 + 贪心(推荐)
核心思路:
- 统计 0~9 的出现次数并计算数字和。
- 根据
sum % 3删除最小的 1 个或 2 个数字,使和能被 3 整除。- 最终从大到小构造最大数字,若全为 0 则返回 “0”。
复杂度分析:
- 时间复杂度:O(n),其中 n 表示数字个数。
- 空间复杂度:O(1),固定 10 位计数数组。
class Solution {
public String largestMultipleOfThree(int[] digits) {
int[] count = new int[10];
int sum = 0;
for (int d : digits) {
count[d]++;
sum += d;
}
if (!adjust(count, sum % 3)) {
return "";
}
StringBuilder builder = new StringBuilder();
for (int d = 9; d >= 0; d--) {
for (int i = 0; i < count[d]; i++) {
builder.append(d);
}
}
if (builder.length() == 0) {
return "";
}
if (builder.charAt(0) == '0') {
return "0";
}
return builder.toString();
}
private boolean adjust(int[] count, int mod) {
if (mod == 0) {
return true;
}
int[] mod1 = {1, 4, 7};
int[] mod2 = {2, 5, 8};
if (mod == 1) {
if (removeOne(count, mod1)) {
return true;
}
return removeTwo(count, mod2);
}
if (removeOne(count, mod2)) {
return true;
}
return removeTwo(count, mod1);
}
private boolean removeOne(int[] count, int[] nums) {
for (int n : nums) {
if (count[n] > 0) {
count[n]--;
return true;
}
}
return false;
}
private boolean removeTwo(int[] count, int[] nums) {
int removed = 0;
for (int n : nums) {
while (count[n] > 0 && removed < 2) {
count[n]--;
removed++;
}
if (removed == 2) {
return true;
}
}
return false;
}
}
func largestMultipleOfThree(digits []int) string {
count := make([]int, 10)
sum := 0
for _, d := range digits {
count[d]++
sum += d
}
if !adjustCount(count, sum%3) {
return ""
}
res := make([]byte, 0, len(digits))
for d := 9; d >= 0; d-- {
for i := 0; i < count[d]; i++ {
res = append(res, byte('0'+d))
}
}
if len(res) == 0 {
return ""
}
if res[0] == '0' {
return "0"
}
return string(res)
}
func adjustCount(count []int, mod int) bool {
if mod == 0 {
return true
}
mod1 := []int{1, 4, 7}
mod2 := []int{2, 5, 8}
if mod == 1 {
if removeOne(count, mod1) {
return true
}
return removeTwo(count, mod2)
}
if removeOne(count, mod2) {
return true
}
return removeTwo(count, mod1)
}
func removeOne(count []int, candidates []int) bool {
for _, n := range candidates {
if count[n] > 0 {
count[n]--
return true
}
}
return false
}
func removeTwo(count []int, candidates []int) bool {
removed := 0
for _, n := range candidates {
for count[n] > 0 && removed < 2 {
count[n]--
removed++
}
if removed == 2 {
return true
}
}
return false
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 179. 最大数 | 中等 | 排序 |
| 402. 移掉 K 位数字 | 中等 | 单调栈 |
| 670. 最大交换 | 中等 | 贪心 |
| 2384. 最大回文数字 | 中等 | 计数 |
| 1005. K 次取反后最大化的数组和 | 简单 | 贪心 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!