编程之美 快速找出机器故障问题

题目:

  简化后问题:有很多机器id,其中只有一个或两个id被丢失,正常情况下每个id个数为2,请问如何找到丢失的id是几。

 

java解法一实现:

 

/**
 * 使用异或操作 X异或X等于0,X异或0等于X,所有元素异或结果就是丢失的元素
 * 如果丢失id个数为2,异或结果就是A异或B的结果,然后将数组分成两组,分别找出来。
 * @author zhaozh
 *
 */
public class MachineErrorID1 {
    private int[] machineIds;//所有机器id列表
    private int[] deleteIdIndexes;//丢失的机器id列表索引
    private int[] lostIds;//丢失的机器id
    
    public MachineErrorID1(int[] machineIds, int[] deleteIdIndexes){
        this.machineIds = new int[machineIds.length - deleteIdIndexes.length];
        int k = 0;
        for(int i = 0; i < machineIds.length; i++){//初始化丢失id后的机器id列表
            boolean flag = true;
            for (int j = 0; j < deleteIdIndexes.length; j++){
                if(i == deleteIdIndexes[j])
                    flag = false;//被删除
            }
            if(flag){
                this.machineIds[k++] = machineIds[i];
            }
        }
        this.deleteIdIndexes = deleteIdIndexes;
        this.lostIds = new int[deleteIdIndexes.length];
    }
    
    public void findLostmachineIds(){
        if(deleteIdIndexes.length == 1){
            lostIds[0] = findLostMachineId();
        }else{
            int i_result = findLostMachineId();
            lostIds = findLostMachineId(i_result);
        }
    }
    
    private int[] findLostMachineId(int i_result){
        if(i_result == 0){
            System.out.println("被删除的两个id是一样的,我找不出来了。");
            return null;
        }else{
            int i_temp = 1;
            while((i_result & i_temp) == 0)
                i_temp = i_temp << 2;
            int[] i_lostIds = new int[2];
            for(int i = 0; i < machineIds.length; i++){
                if((i_temp & machineIds[i]) == 0){
                    i_lostIds[0] = i_lostIds[0] ^ machineIds[i];
                }else if((i_temp & machineIds[i]) != 0){
                    i_lostIds[1] = i_lostIds[1] ^ machineIds[i];
                }
            }
            return i_lostIds;
        }
    }
    
    private int findLostMachineId(){
        int i_lostId = 0;
        for (int i = 0; i < machineIds.length; i++) {
            i_lostId = i_lostId ^ machineIds[i];
        }
        return i_lostId;
    }
    
    public void output(){
        if(lostIds != null){
            System.out.println("the lost machine id is :" );
            for(int i = 0; i < lostIds.length; i++){
                System.out.print("  " + lostIds[i]);
            }
        }
    }

    public static void main(String[] args) {
        int[] machineIds = new int[]{1,1,2,2,3,3,4,4,5,5};
        int[] deleteIdIndexes = new int[]{1,9};
        
        MachineErrorID1 machineErrorId = new MachineErrorID1(machineIds, deleteIdIndexes);
        machineErrorId.findLostmachineIds();
        machineErrorId.output();
    }

}

 

java解法二实现:

 

/**
 * 原理:末丢失id前的id总和,减去丢失id后的总和,就是丢失的id。
 * 如果丢失一下,就可以直接找出来
 * 如果丢失的是两个,就要再构造一个方程,如丢失前后,所有id的乘积之差(防止溢出也可以是 所有id的平方和)。由x+y=a,x*y=b求出x,y
 * @author zhaozh
 *
 */
public class MachineErrorID2 {
    private int[] machineIds;//所有机器id列表
    private int[] deleteIdIndexes;//丢失的机器id列表索引
    private int[] lostIds;//丢失的机器id
    private int sum_ids;//丢失前id的和
    private int mult_ids;//丢失前id的积
    
    public MachineErrorID2(int[] machineIds, int[] deleteIdIndexes){
        this.machineIds = new int[machineIds.length - deleteIdIndexes.length];
        int k = 0;
        for(int i = 0; i < machineIds.length; i++){//初始化丢失id后的机器id列表
            boolean flag = true;
            for (int j = 0; j < deleteIdIndexes.length; j++){
                if(i == deleteIdIndexes[j])
                    flag = false;//被删除
            }
            if(flag){
                this.machineIds[k++] = machineIds[i];
            }
        }
        for(int i = 0; i < machineIds.length; i++){//计算id的和
            sum_ids += machineIds[i];
        }
        if(deleteIdIndexes.length > 1){//计算id的积
            mult_ids = machineIds[0];
            for(int i = 1; i < machineIds.length; i++){
                mult_ids *= machineIds[i];
            }
        }
        this.deleteIdIndexes = deleteIdIndexes;
        this.lostIds = new int[deleteIdIndexes.length];
    }
    
    public void findLostmachineIds(){
        if(deleteIdIndexes.length == 1){
            lostIds[0] = sumMachineId();
        }else{
            int i_multi = multiMachineId();
            int i_sum = sumMachineId();
            lostIds[1] = (int) ((i_sum + Math.sqrt(i_sum * i_sum - 4 * i_multi))/2);
            lostIds[0] = i_sum - lostIds[1];
        }
    }
    
    private int multiMachineId(){
        int i_multids = machineIds[0];
        for(int i = 1; i < machineIds.length; i++){
            i_multids *= machineIds[i];
        }
        return this.mult_ids / i_multids;
    }
    
    private int sumMachineId(){
        int i_lostId = 0;
        for (int i = 0; i < machineIds.length; i++) {
            i_lostId += machineIds[i];
        }
        return this.sum_ids - i_lostId;
    }
    
    public void output(){
        if(lostIds != null){
            System.out.println("the lost machine id is :" );
            for(int i = 0; i < lostIds.length; i++){
                System.out.print("  " + lostIds[i]);
            }
        }
    }

    public static void main(String[] args) {
        int[] machineIds = new int[]{1,1,2,2,3,3,4,4,5,5};
        int[] deleteIdIndexes = new int[]{1,9};
        
        MachineErrorID2 machineErrorId = new MachineErrorID2(machineIds, deleteIdIndexes);
        machineErrorId.findLostmachineIds();
        machineErrorId.output();
    }

}

输出结果:

the lost machine id is :
  1  5

posted @ 2015-05-14 18:11  华仔逍遥刀客  阅读(200)  评论(0编辑  收藏  举报