力扣1363——形成三的最大倍数
1363. 形成三的最大倍数
给你一个整数数组 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
- 返回的结果不应包含不必要的前导零。
题解
这道题讨论的是三的倍数,而我们知道一个数是不是三的倍数,只需要看这个数的各个位数的和是不是三的倍数就可以。
那么,我们可以将输入的每个数字分为三类[0,3,6,9] [1,4,7] [2,5,8],对3求余的结果分别是0 1 2,后面以0类 1类 2类表示
因此我们只需要考虑这三类数字的个数之间的关系就可以了
创建了三个队首为最大值的优先队列 分别是q q1 q2,初始里面装的内容分别是 0 1 2这三类数字
首先,0类数字可以无脑放到最后需要输出的内容中,1类和2类则需要考虑二者的个数关系进行调整,将里面的数字放入到q中
所以最后q中的数字就是我们需要的了
不要忘记考虑一种情况,就是给定的数字是多个0,那么只要返回"0"就可以了
对了,这道题主要是想办法在可以搞出最多个数的数字的情况下,尽可能使每个数字更大
令size1表示1类个个数,size2表示2类的个数,关系图如下所示
代码
点击查看代码
class Solution {
public:
string largestMultipleOfThree(vector<int>& digits) {
priority_queue<int> q,q1,q2;
for(int i = 0;i < digits.size();i++){
if(digits[i] % 3 == 0) q.push(digits[i]);
else if(digits[i] % 3 == 1) q1.push(digits[i]);
else q2.push(digits[i]);
}
int size1 = q1.size(),size2 = q2.size();
/* for(int i = 0; i < size1; i++) {
cout<<q1.top();
q1.pop();
}
cout<<endl;
for(int i = 0; i < size2; i++) {
cout<<q2.top();
q2.pop();
}
cout<<endl;
return "0";*/
if(size1 == size2){ //如果q1 和 q2一样多,则直接一一配对就可以了
for(int i = 0;i < size1; i++){
q.push(q1.top());
q.push(q2.top());
//cout<<q1.top()<<" "<<q2.top()<<endl;
q1.pop();
q2.pop();
//cout<<q1.size()<<" "<<q2.size()<<endl;
}
}
else if(size1 > size2){ //q1的数量大于q2
int diff = ( size1 - size2 ) % 3;
if(diff == 0){ // 将二者都放进去
for(int i = 0;i < size1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0;i < size2; i++){
q.push(q2.top());
q2.pop();
}
}
else if (diff == 1){ // q1都下一个,剩下都放进去 q2都放进去
for(int i = 0;i < size1 - 1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0;i < size2 ; i++){
q.push(q2.top());
//cout<<q2.top()<<endl;
q2.pop();
}
}
else{ //
//
/*int k = size1 / 3 * 3;
for(int i = 0 ;i < k ;i++){
q.push(q1.top());
q1.pop();
}
k = size2 / 3 * 3;
for(int i = 0 ;i < k ;i++){
q.push(q2.top());
q2.pop();
}
while(q1.size() > 0 && q2.size() > 0){
q.push(q1.top());
q.push(q2.top());
q1.pop();
q2.pop();
}*/
if(size2 == 0){
for(int i = 0 ;i < size1 - 2; i++){
q.push(q1.top());
q1.pop();
}
}
else{
for(int i = 0;i < size1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0; i < size2 - 1; i++){
q.push(q2.top());
q2.pop();
}
}
}
}
else{ // q2 > q1
int diff = ( size2 - size1 ) %3;
if(diff == 0){//将二者都放进去
for(int i = 0;i < size1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0;i < size2; i++){
q.push(q2.top());
q2.pop();
}
}
else if(diff == 1){
for(int i = 0;i < size1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0;i < size2 - 1; i++){
q.push(q2.top());
q2.pop();
}
}
else{
if(size1 == 0){
for(int i = 0;i < size2 - 2;i++){
q.push(q2.top());
q2.pop();
}
}
else{
for(int i = 0; i < size2;i++) {
q.push(q2.top());
q2.pop();
}
for(int i = 0; i < size1 - 1; i++){
q.push(q1.top());
q1.pop();
}
}
}
}
if(q.size() == 0) return "";
else {
string ans;
if(q.top() == 0) return "0";
while(q.size() > 0){
ans += ('0' + q.top());
//cout<<q.top()<<endl;
q.pop();
}
return ans;
}
}
};
简单题解
上面的题解是我的第一想法,当我把这个想法实现之后,突然发现自己想复杂了
我们可以直接对给的所有数字进行相加得到结果res
然后可以分为三种情况进行讨论
- 1 res % 3 == 0,此时我们可以直接将所有数字直接按照从大到小输出就行
- 2 res % 3 == 1,此时存在两种情况
- 1 size1 == 0,此时只需要让2类数字留下最小的两个,剩下都输出
- 2 size1 != 0,此时只需要让1类数字留下最小的一个,剩下都输出
- 3 res % 3 == 2,此时存在两种情况
- 1 size2 == 0,此时让1类留下两个,剩下都输出
- 2 size2 != 0,此时让2类留下一,剩下都输出就可以
代码
点击查看代码
class Solution {
public:
string largestMultipleOfThree(vector<int>& digits) {
priority_queue<int> q,q1,q2;
for(int i = 0;i < digits.size();i++){
if(digits[i] % 3 == 0) q.push(digits[i]);
else if(digits[i] % 3 == 1) q1.push(digits[i]);
else q2.push(digits[i]);
}
int size1 = q1.size(),size2 = q2.size();
if((size1 + size2 * 2) % 3 == 0){
for(int i = 0;i < size1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0;i < size2; i++){
q.push(q2.top());
q2.pop();
}
}
else if((size1 + size2 * 2) % 3 == 1){
if(size1 == 0){
for(int i = 0; i < size2 - 2; i++){
q.push(q2.top());
q2.pop();
}
}
else{
for(int i = 0; i < size1 - 1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0; i < size2; i++){
q.push(q2.top());
q2.pop();
}
}
}
else{
if(size2 == 0){
for(int i = 0; i < size1 - 2; i++){
q.push(q1.top());
q1.pop();
}
}
else{
for(int i = 0; i < size1; i++){
q.push(q1.top());
q1.pop();
}
for(int i = 0; i < size2 - 1; i++){
q.push(q2.top());
q2.pop();
}
}
}
if(q.size() == 0) return "";
else {
string ans;
if(q.top() == 0) return "0";
while(q.size() > 0){
ans += ('0' + q.top());
//cout<<q.top()<<endl;
q.pop();
}
return ans;
}
}
};
作者:孙建钊
出处:http://www.cnblogs.com/sunjianzhao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。