梯度收费算法

交电费按梯度收费,总用电
小于等于5度电,每度30元;
大于5度小于等于20度的,每度15元;
大于20度小于等于50度的,每度10元。
大于50度小于等于100度,每度9元;
大于100度小于等于500度,每度8元;
大于500度小于等于1000度,每度7元;
大于1000度小于等于2000度,每度6元;
大于2000度小于等于3000度,每度5元;
大于3000度小于等于4000度,每度4元;
大于4000度小于等于5000度,每度3元;
大于5000度小于等于6000度,每度2元;
大于 6000度 ,每度1元。

例如,某月总用电量为6度,则电费为5*30+1*15 = 165元。

算法实现:

根据题目把交费电量分为12个区间,用两个数组分别存储每个区间的度数及价格,算出每个区间应交费多少,每个区间的交费加起来即可。

例如第一个区间是5度,第二个区间是6度至20度,说明第二个区间的度数为15度。先看总电量是否大于第一个区间的度数5度,如果大于,则5度在第一个区间,按照第一个区间缴费,总电量减5,剩下的电量又看是否大于第二个区间的度数....

下面写了两个方法,第1个是递归方法,代码简单,也好理解,用到了两个额外数组;第2个非递归,代码多一点,用到了一个额外数组。

public class DegreesTest {
    // 区间度数数组
    public static double[] sectionDegrees = new double[]{5, 15, 30, 50, 400, 500, 1000, 1000, 1000, 1000, 1000, 0};
    // 区间价格数组
    public static double[] sectionPrices = new double[]{30, 15, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};


    public static void main(String[] args) {
        //方法1
        System.out.println(compute2(6, 0)); //165
        //方法2
        System.out.println(compute(6)); //165
    }

    /**
     * 计算电费方法1 - 递归 - 需要用到 “区间度数数组 sectionDegrees”及 “区间价格数组 sectionPrices”
     *
     * @param degree 剩余用电度数
     * @param i      区间下标
     * @return 总电费
     */
    public static double compute2(double degree, int i) {
        // 度数为0,直接返回
        if (degree == 0) {
            return 0;
        }
        // 剩余度数比当前区间度数大
        if (degree > sectionDegrees[i]) {
            if (sectionDegrees[i] == 0) { //如果是最后一个区间,则总电费=剩余电量*单价1
                return degree * sectionPrices[i];
            }
            //总电费=当前区间电费+后面区间电费 - 递归计算
            return sectionDegrees[i] * sectionPrices[i] + compute2(degree - sectionDegrees[i], i + 1);
        } else { // 剩余度数小于等于当前区间度数
            return degree * sectionPrices[i];
        }
    }

    /**
     * 计算电费方法2 - 需要用到 “区间度数数组 sectionDegrees”
     *
     * @param degree 用电度数
     * @return 总电费
     */
    public static double compute(double degree) {
        // 计算每个区间的度数
        for (int i = 0; i < sectionDegrees.length; i++) {
            // 剩余度数为0,将当前的区间度数清空
            if (degree == 0) {
                sectionDegrees[i] = 0;
                continue;
            }
            // 最后一个区间,直接设置剩余的度数
            if (i == sectionDegrees.length - 1) {
                sectionDegrees[i] = degree;
                continue;
            }
            // 大于区间度数,减去当前区间度数,计算剩余度数
            if (degree > sectionDegrees[i]) {
                degree -= sectionDegrees[i];
            }
            // 小于区间度数,将当前区间度数设置为剩余度数
            else {
                sectionDegrees[i] = degree;
                degree = 0;
            }
        }
        // 总电费 = 每个区间电费之和
        double result = 30 * sectionDegrees[0] + 15 * sectionDegrees[1] + 10 * sectionDegrees[2]
                + 9 * sectionDegrees[3] + 8 * sectionDegrees[4] + 7 * sectionDegrees[5] + 6 * sectionDegrees[6]
                + 5 * sectionDegrees[7] + 4 * sectionDegrees[8] + 3 * sectionDegrees[9] + 2 * sectionDegrees[10]
                + sectionDegrees[11];
        return result;
    }

}

你可能感兴趣的:(#,面试题,算法,算法,java,jvm,梯度收费)