面试准备------笔试中的算法题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a940902940902/article/details/89303965
  1. 数组中有n个正整数,每次可以选择其中一个数进行乘2或者除以2的操作(对于奇数除以2取其整数部分),求使得数组中的n个数变成相同的数的最小操作次数
    样例:
    2,4,8 输出 2(对2进行乘2操作,对8进行除以2操作)
    3,7,14 输出3 (对7进行除以2操作,对14进行两次除以2操作)
    2,3,7 输出4 (对2进行除以2操作,对3进行除以2操作,对7进行两次除以2操作)
题解:
该题的关键思路有如下几点:1.一个偶数可以通过不断的除以2变化为一个奇数  2.不同的奇数只有可能由较大的奇数变化为较小的奇数 (如 3,7)或者同时变为1(如3,5)

public class LeastOperation {
    
    public int getLeastOperation(int[]nums){
        int[]operationNum=new int[nums.length];
        // 1.将所有的数字变为奇数
        for(int i=0;i<nums.length;i++){
            while(nums[i]%2==0){
                nums[i]=nums[i]/2;
                operationNum[i]=operationNum[i]+1;
            }
        }
        // 2.判断是否为相等的奇数
        boolean isSame=isSame(nums);
        if(isSame){
           // 相等则取中位数 到中位数的距离就是变化的最小次数
            Arrays.sort(operationNum);
            int begin=0;
            int end=operationNum.length-1;
            int totalNum=0;
            while(end>begin){
                totalNum=operationNum[end]-operationNum[begin];
                begin++;
                end--;
            }
            return totalNum;
        }else{
            boolean same=false;
            while(!same) {
               // 得到最小值 并将其他值做除以2的操作 操作次数加一  
                int min = getMin(nums);
                for (int i = 0; i < nums.length; i++) {
                    while (nums[i] > min) {
                        nums[i] = nums[i] / 2;
                        operationNum[i] = operationNum[i] + 1;
                    }
                }
               same=isSame(nums);
            }
            int result=0;
            for(int num:operationNum){
                result+=num;
            }
            return result;
        }
        
    }
    public boolean isSame(int[]nums){
        int num=nums[0];
        boolean isSame=true;
        for(int i=1;i<nums.length;i++){
            if(nums[i]!=num){
                isSame=false;
                break;
            }
        }
        return isSame;
    }
    public int getMin(int[]nums){
        int min=nums[0];
        for(int i=0;i<nums.length;i++){
            if(nums[i]<min){
                min=nums[i];
            }
        }
        return min;
    }
}

2 在一条直线上有n个村庄 每个村庄都有对红酒的需求量 负数表示需求 整数表示供给 求最小的运送量(UVA11054)

这道题采用的想法是贪心的做法 对于最左侧的村庄而言如果它是对酒有需求的 那么他的需求量一定是其右侧的邻居提供的(如果右侧邻居无法提供则也是先将红酒转移到其右侧邻居 再转移到它的位置 )其实可以将需求和供给同等对待 例如 【-1,-4,3,2】 最左侧转移-1个单位的红酒到其右邻居 则其右邻居变为-5个单位的红酒 继续以此类推则得最终结果

public static int getMinTotal(int[] wine){
        int total=0;
        int tmp=0;
        for(int i=0;i<wine.length;i++){
            total+=Math.abs(tmp);
            tmp+=wine[i];
        }
        return total;
    }

    public static void main(String[] args) {
        Scanner scan =new Scanner(System.in);
        int num=scan.nextInt();
        int[] totalWine=new int[num];
        for(int i=0;i<num;i++){
            totalWine[i]=scan.nextInt();
        }
        int result=getMinTotal(totalWine);
        System.out.println(result);
    }

猜你喜欢

转载自blog.csdn.net/a940902940902/article/details/89303965