You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

油耗追踪程序日期与里程表输入验证算法实现优化求助

油耗追踪程序日期与里程验证算法优化方案

现有问题梳理

  • 逻辑缺陷:未完整覆盖同日期输入的校验规则、插入列表末尾的校验逻辑缺失、验证不通过时仍然输出添加成功提示
  • 效率问题:当前用线性遍历查找插入位置和查重,数据量较大时时间复杂度为O(n),性能较差

优化实现思路

1. 效率优化

由于数据集本身是按时间倒序排序的,可使用二分查找定位插入位置,将查找复杂度从O(n)降低到O(logn);如果数据集规模较大,可额外用HashSet存储<日期,里程>的组合,把查重复杂度降到O(1),小数据集保留线性遍历也可满足需求。

2. 校验逻辑完善

严格对齐规则实现分层校验:

  1. 第一步先查重,日期+里程组合重复直接拦截
  2. 找到插入位置后分三种场景校验:
    • 插入顶部(索引为0):如果输入日期晚于最新条目,里程必须大于最新条目里程;如果和最新条目日期相同,里程要小于最新条目里程,同时早于更早日期的对应里程
    • 插入中间:输入里程必须小于插入位置前一条的里程,大于插入位置当前条的里程
    • 插入末尾:输入里程必须小于最早条目的里程

优化后核心代码示例

import java.util.Objects;

// 可选:封装加油条目,统一管理日期和里程,降低维护成本
record FuelRecord(Date date, int odometer) {}

public class OdometerValidator {
    public static Date[] dates = new Date[3];
    public static int[] odometers = new int[3];

    // 初始化示例数据集
    static {
        dates[0] = new Date(2021,2,14);
        dates[1] = new Date(2021,2,5);
        dates[2] = new Date(2021,2,4);
        odometers[0] = 156830;
        odometers[1] = 156572;
        odometers[2] = 156255;
    }

    public static void main(String[] args) {
        // 测试输入
        Date inputDate = new Date(2021,2,14);
        int inputOdo = 156255;

        // 第一步:重复校验
        if (hasDuplicate(inputDate, inputOdo)) {
            System.out.println("该日期和里程组合的加油记录已存在。");
            return;
        }

        // 第二步:二分查找插入位置,复杂度O(logn)
        int insertIndex = findInsertIndex(inputDate);
        boolean isValid = true;

        // 第三步:按插入位置做里程校验
        if (insertIndex == 0) {
            // 插入顶部场景
            if (inputDate.compareTo(dates[0]) > 0) {
                // 日期晚于最新条目,里程必须大于最新里程
                if (inputOdo <= odometers[0]) {
                    System.out.printf("里程不能小于您此前记录的加油里程:%d(日期:%s)%n", odometers[0], dates[0]);
                    isValid = false;
                }
            } else {
                // 和最新条目日期相同,里程需符合相邻递增规则
                if (inputOdo >= odometers[0] || (dates.length > 1 && inputOdo <= odometers[1])) {
                    System.out.printf("里程需介于%d(日期:%s)和%d(日期:%s)之间%n",
                            odometers[1], dates[1], odometers[0], dates[0]);
                    isValid = false;
                }
            }
        } else if (insertIndex == dates.length) {
            // 插入末尾场景
            if (inputOdo >= odometers[dates.length - 1]) {
                System.out.printf("里程不能大于您此前记录的最早加油里程:%d(日期:%s)%n", odometers[dates.length-1], dates[dates.length-1]);
                isValid = false;
            }
        } else {
            // 插入中间场景
            int upperOdo = odometers[insertIndex - 1];
            int lowerOdo = odometers[insertIndex];
            if (inputOdo >= upperOdo || inputOdo <= lowerOdo) {
                System.out.printf("里程需介于%d(日期:%s)和%d(日期:%s)之间%n", lowerOdo, dates[insertIndex], upperOdo, dates[insertIndex-1]);
                isValid = false;
            }
        }

        if (isValid) {
            System.out.println("加油记录添加成功!");
            // 此处可实现数组扩容、插入新条目的逻辑
        }
    }

    // 二分查找定位插入位置
    private static int findInsertIndex(Date inputDate) {
        int left = 0, right = dates.length;
        while (left < right) {
            int mid = (left + right) / 2;
            if (inputDate.compareTo(dates[mid]) >= 0) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

    // 查重方法,大数据集可替换为HashSet实现O(1)查重
    private static boolean hasDuplicate(Date date, int odo) {
        for (int i = 0; i < dates.length; i++) {
            if (date.equals(dates[i]) && odo == odometers[i]) {
                return true;
            }
        }
        return false;
    }

    // 简化日期实现,仅做示例,生产环境可使用java.time包下的LocalDate
    static class Date implements Comparable<Date> {
        int year, month, day;
        public Date(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
        }
        @Override
        public int compareTo(Date o) {
            if (year != o.year) return year - o.year;
            if (month != o.month) return month - o.month;
            return day - o.day;
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Date date = (Date) o;
            return year == date.year && month == date.month && day == date.day;
        }
        @Override
        public int hashCode() {
            return Objects.hash(year, month, day);
        }
        @Override
        public String toString() {
            return year + "-" + month + "-" + day;
        }
    }
}

内容的提问来源于stack exchange,提问作者aldrich19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 00:15:03