編程之美——快速找出機器故障問題

題目:

  簡化後問題:有很多機器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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章