文章目录
- [一. 力扣 [1262. 可被三整除的最大和](https://leetcode.cn/problems/greatest-sum-divisible-by-three/description/)](#一. 力扣 1262. 可被三整除的最大和)
-
- [1. 题目解析](#1. 题目解析)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
- [二. 力扣 [1054. 距离相等的条形码](https://leetcode.cn/problems/distant-barcodes/description/)](#二. 力扣 1054. 距离相等的条形码)
-
- [1. 题目解析](#1. 题目解析)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
- [三. 力扣 [767. 重构字符串](http://leetcode.cn/problems/reorganize-string/description/)](#三. 力扣 767. 重构字符串)
-
- [1. 题目解析](#1. 题目解析)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
一. 力扣 1262. 可被三整除的最大和
1. 题目解析
2. 算法原理
主要思想是正难则反, 先求总和sum, 再根据情况讨论, 本题有贪心和动态规划两种解法, 这里只给出贪心
3. 代码
java
class Solution {
public int maxSumDivThree(int[] nums) {
int sum = 0;
for (int x : nums) {
sum += x;
}
if (sum % 3 == 0) {
return sum;
} else if (sum % 3 == 1) {
int min1 = 0x3f3f3f3f, min2 = 0x3f3f3f3f, min = 0x3f3f3f3f;
for (int x : nums) {
if (x % 3 == 1 && x < min) {
min = x;
}
if (x % 3 == 2) {
if (x <= min1) {
min2 = min1;
min1 = x;
} else if (min1 < x && x < min2) {
min2 = x;
}
}
}
return Math.max(sum - min, sum - min1 - min2);
}else {
int min1 = 0x3f3f3f3f, min2 = 0x3f3f3f3f, min = 0x3f3f3f3f;
for (int x : nums) {
if (x % 3 == 2 && x < min) {
min = x;
}
if (x % 3 == 1) {
if (x <= min1) {
min2 = min1;
min1 = x;
} else if (min1 < x && x < min2) {
min2 = x;
}
}
}
return Math.max(sum - min, sum - min1 - min2);
}
}
}
二. 力扣 1054. 距离相等的条形码
1. 题目解析
有多个相同元素的数组, 重新排列使其相邻元素不相同
2. 算法原理
这道题的算法原理很简单, 模拟一遍, 间隔填写
3. 代码
java
class Solution {
Map<Integer, Integer> hash;
public int[] rearrangeBarcodes(int[] barcodes) {
hash = new HashMap<>();
int val = 0, count = 0;
int n = barcodes.length;
// 把元素与个数丢入哈希表, 同时找出最多的相同元素
for (int x : barcodes) {
hash.put(x, hash.getOrDefault(x, 0) + 1);
if (count < hash.get(x)) {
count = hash.get(x);
val = x;
}
}
int[] ret = new int[n];
// 图中第一个位置对应的就是0号位置
int index = 0;
for (int i = 0; i < count; i++) {
ret[index] = val;
index += 2;
}
// 删除val
hash.remove(val);
// 添加其他元素, 遍历key, 再在内循环遍历出现的次数
for (int x : hash.keySet()) {
for (int i = 0; i < hash.get(x); i++) {
// 当index大于数组长度时, 说明偶数位置(图中的奇数位置)已经遍历完, 这里将index从1开始, 因为元素个数和ret长度一致, 因此仅会修改一次
if (index > n - 1) index = 1;
ret[index] = x;
index += 2;
}
}
return ret;
}
}
三. 力扣 767. 重构字符串
1. 题目解析
和上道题很相似, 这里无非换成了字符, 同时要注意, 可能存在无法排列的情况
2. 算法原理
当单一字符的个数超过了(n + 1) / 2时, 无论怎么排序都无法满足题目要求
3. 代码
java
class Solution {
public String reorganizeString(String s) {
char[] c = s.toCharArray();
int n = c.length;
// 因为这里全是小写字符, 用数组代替哈希表
int[] hash = new int[26];
char val = '0';
int count = 0;
for (char ch : c) {
hash[ch - 'a']++;
if (count < hash[ch - 'a']) {
val = ch;
count = hash[ch - 'a'];
}
}
if (count > (n + 1) / 2) return "";
char[] ret = new char[n];
int index = 0;
for (int i = 0; i < count; i++) {
ret[index] = val;
index += 2;
}
hash[val - 'a'] = 0;
for (int i = 0; i < 26; i++) {
for (int j = 0; j < hash[i]; j++) {
if (index > n - 1) index = 1;
ret[index] = (char)(i + 'a');
index += 2;
}
}
return new String(ret);
}
}





