求和函数
public int sum(int[] weights,int start,int end){
int res = 0;
for(;start<=end;start++){
res+=weights[start];
}
return res;
}
核心内容(全是if、else,最深是三层,所以最多比较三次即可得到假币更重还是更轻)
public void pp(int[] weights){
int size = weights.length;
// 第一步,把硬币分为两个相同的区间,(如果为奇数,则取出最后一个)
int left = 0,leftS=0,leftE=size/2-1;
int right = 0,rightS=size/2,rightE=size-1-weights.size()%2;// 取出了最后一个元素,保证两个硬币区间的硬币数一致
left = sum(weights,leftS,leftE);
right = sum(weights,rightS,rightE);
if(left==right){//硬币在取出的那个硬币中
int newLeft = left+weights[size-1]-weights[0];
if(newLeft < right){
qDebug() << "假币更轻" ;
}else if(newLeft > right){
qDebug() << "假币更重" ;
}else{
qDebug() << "没有假币" ;
}
}else{//假币可能在left堆或者right中,我这里直接判断左堆,把左堆拆成两个相同的区间,如果左堆为奇数堆,就从右堆借1个
int leftLS = 0,leftLE = (leftE+1)/2-1+(leftE+1)%2;//如果原为奇数,则+1,即(leftE+1)%2
int leftRS = leftLE+1, leftRE = leftRS+(leftLE-leftLS);
int leftL = sum(weights,leftLS,leftLE);
int leftR = sum(weights,leftRS,leftRE);
if(leftL==leftR){
// 如果从右堆中借了数据,则会影响判断,所以这里加一个判断
if(weights[0]!=weights[leftRE]){
if(weights[leftRS]==weights[leftRE]){
// 假币是我借的,它是右边的
qDebug() << "假币在右边" ;
if(left<right){
ui->res->setText("假币更重!");
qDebug() << "假币更重" ;
}else{
ui->res->setText("假币更轻!");
qDebug() << "假币更轻" ;
}
}else{
// 假币本身就是我这边的
qDebug() << "假币在左边" ;
if(left<right){
ui->res->setText("假币更轻!");
qDebug() << "假币更轻" ;
}else{
ui->res->setText("假币更重!");
qDebug() << "假币更重" ;
}
}
}else{
qDebug() << "假币在右堆" ;
// 直接判断假币是轻还是重!
if(left<right){
ui->res->setText("假币更重!");
qDebug() << "假币更重" ;
}else{
ui->res->setText("假币更轻!");
qDebug() << "假币更轻" ;
}
}
}else{
// 确定假币在左left区间中
// 在右堆中取出相同长度的硬币,和左堆的其中某个比较,判断假币在哪里
int rightRE = size-1,rightRS = rightRE-(leftRE-leftRS);
int rightR = sum(weights,rightRS,rightRE);
if(rightR!=leftL){
qDebug() << "假币在左左堆" ;
if(rightR<leftL){
ui->res->setText("假币更重!");
qDebug() << "假币更重" ;
}else{
ui->res->setText("假币更轻!");
qDebug() << "假币更轻" ;
}
}else{
qDebug() << "假币在左右堆" ;
if(rightR<leftR){
ui->res->setText("假币更重!");
qDebug() << "假币更重" ;
}else{
ui->res->setText("假币更轻!");
qDebug() << "假币更轻" ;
}
}
}
}
}