问题分析:
题目描述一大堆,实际上就是让你写大数加法,这就是一个脑筋急转弯。示例还特地不按数字大小排序的答案给出来,
就是怕你发现是找最大的x.size()-k+1个数字组成的最大数字
因为其他操作都是截取字符串,和求k-1个个位数的和。
最大和一定是最大的x.size.()-(k-1)个数字组成的数字和后面(k-1)每单个数字的和。
如何获取前x.size()-(k-1)个最大的数字且组合起来是最大的数字,只需要让字符串降序排列就行了,
然后调用一次substr,。接着计算后面(k-1)个数字的和与前面截取的字符串相加。因为字符串可能很长,
所以不能直接转数字相加,那么问题就变成了编写一个大数加法的问题。而因为题目已经限定了字符串最大长度。
所以后面(k-1)直接计算数字的和,最后转成字符串就行。
复杂度分析:
时间复杂度O(n):排序算法,库函数应该不会太大,截取子串单次操作,计算后k位和O(k),大数加法:O(max(k-1,x.size()-k+1))。
空间复杂度:O(n):取决于字符串大小和k的大小,主要是用于返回结果。
具体代码看下面:
class Solution {
public:
static bool cmp(char &a,char &b){
return a>b;
}
string Maxsumforknumers(string x, int k) {
if(k==1) return x;
string res,tmp_str;
int tmp=0;
if(k==x.size()) {
for(int i=0;i<x.size();++i) tmp+=x[i]-'0';
res=to_string(tmp);
return res;
}
sort(x.begin(),x.end(),cmp);
res=x.substr(0,x.size()-k+1);
for(int i=x.size()-k+1;i<x.size();++i) tmp+=x[i]-'0';
tmp_str=to_string(tmp);
res=sadds(res,tmp_str);
return res;
}
string sadds(string res,string str2) {
if(str2=="0") return res;
if(res.size()<str2.size()) swap(res,str2);//保证res是最大长度的
int k=0;//进位标志
int x;//保存两个字符串每位相加的和,需加进位。从底到高
int m=res.size()-1;
int n=str2.size()-1;
while(n>=0) {
x=res[m]-'0'+str2[n]-'0'+k;
res[m]=(x%10)+'0';
k=x/10;
--m,--n;
}
if(m==n&&k) {//当两个字符串长度相等时,需要考虑最后一次的进位
res.insert(res.begin(),'1');
return res;
}
while(m>=0&&k) {//较短字符串已经结束了,每次就看是否有进位
x=res[m]-'0'+k;
res[m]=(x%10)+'0';
k=x/10;
--m;
}
//如果上面一步一直到第一位,就需要看是否有进位
if(m==-1&&k) res.insert(res.begin(),'1');
return res;
}
};

京公网安备 11010502036488号