从10000个包裹中找出1个打包美诚月饼的包裹,这在生活中是一个很常见,很现实的问题,同时这也是一个开放性的问题,所以不要局限了我们的思路。孙子兵法说,上兵伐谋,其次伐交,其次伐兵,其下攻城。其中涉及到的利益相关方包括客户、我(打包员)和老板,如何高效解决这个问题呢。
其实很多职场新人一旦遇到类似的状况,第一反应是“攻城”,想尽办法找到那个包裹,当然“”攻城”的办法我们后面会讲。
如果是我,我会怎么来处理呢?我会拿出这样一个方案供老板来选择,先发一个公告,声称本批次发货店铺在做活动,其中有一个超级幸运客户,他收到的月饼实际上是美诚月饼。如果美诚月饼比美心月饼的口碑品质好,这本身就足以作为奖励,相反的话可以提供复购打折券或者升级VIP,自然提供无偿退换货的方案。只要老板同意这个方案,我是不是不用加班了,也不用连累同事加班了,这样就彻底把问题给消灭,把一个技术性的失误化解成为一个公关问题,甚至还增添了购物过程中的趣味性。
如果万一万一老板是个死脑筋,不知变通要你必须把那个异类找出来。这10000个包裹对我而言完全是个黑盒,除了外包装上的配送信息不一样,啥也看不出来,也尽量不要去破坏包裹,这样又会导致大量返工,甚至会造成延迟发货。那就开始我们的“攻城”方案吧。那么我们知道的信息是啥,两种品牌月饼的配料表、重量。
重量是个关键信息,配方不同、尺寸差异,包装差异,必然导致两盒不同的月饼重量的差异。我们先分别取一盒月饼样品称重,记录美心的重量为Wmx,美诚月饼的重量的Wmc,然后用二分搜索法来查找。当然如果有好基友相助,也可以分包给好基友完成一定的工作量。
其实我们只需要知道美心月饼和美诚月饼的包裹孰轻孰重,我们每次比较两堆包裹的总重量就能知道那个幸运包裹在哪里,直到剩下刚好两个。下面就是代码和伪代码
package com.wen;
public class FindLuckyOne {
public static void main(String[] args) {
// 单个美心月饼包裹的重量,需要称重
Double Wmx;
// 单个美诚月饼包裹的重量,需要称重
Double Wmc;
Double[] packages=new Double[10000];
int left=0;
int right=packages.length;
int mid=(left+right)/2;
while (left<right){
if(Wmx>Wmc){ // 美心比较重,那个包裹在更轻的那一堆
if(sumWight(packages,left,mid)<sumWight(packages,mid+1,right)){
right=mid;
}else{
left=mid+1;
}
}else{ // 美心比较轻,那个包裹在更重的那一堆
if(sumWight(packages,left,mid)<sumWight(packages,mid+1,right)){
left=mid+1;
}else{
right=mid;
}
}
// 处理不能刚好分两组的情况
if((right-left+1)%2==1){
// 称最后一个包裹重量,如果找到就结束了 return ,否则剔除继续找
right=right-1;
}
mid=(left+right)/2;
}
// 最后下标为Max就是我们的目标
}
// 这里需要对一堆包裹称重
public static Double sumWight(Double [] arr,int start,int end){
return 0D;
}
其实在分组中可能出现不能刚好分两组的情况(奇数个包裹),我们可以在上一轮比较后,随机取出一个包裹和单个美心或美诚月饼的包裹比较重量,这里也有概率直接找到,找不到就剔除,继续分组比较。