带ttl的LRU 家人们说我写的对吗

可运行版本

import java.util.HashMap;
import java.util.Map;

class LRUCache {
    class DLinkedList{
        int key;
        int val;
        DLinkedList next;
        DLinkedList prev;
        long timeStamp;
        public DLinkedList(){
            this.timeStamp = System.currentTimeMillis();
        }
        public DLinkedList(int key,int val){
            this.key = key;
            this.val = val;
            this.timeStamp = System.currentTimeMillis();
        }
    }

    int capacity;
    int size;
    DLinkedList head;
    DLinkedList tail;
    Map<Integer,DLinkedList> map;
    long ttl;
    public LRUCache(int capacity,long ttl){
        this.capacity = capacity;
        size = 0;
        head = new DLinkedList();
        tail = new DLinkedList();
        head.next=tail;
        tail.prev = head;
        map = new HashMap<>();
        this.ttl = ttl;
    }

    public void addToHead(DLinkedList node){
        node.next = head.next;
        head.next.prev = node;
        node.prev = head;
        head.next = node;
    }

    public void removeOne(DLinkedList node){
        node.next.prev = node.prev;
        node.prev.next = node.next;
    }

    public boolean isExpired(DLinkedList node){
        long now = System.currentTimeMillis();
        long diff = now-node.timeStamp;
        if(diff>ttl){
            return true;//true是过期了的意思 false才是没过期!!!
        }
        return false;
    }

    public int get(int key){
        if(!map.containsKey(key)){
            return -1;
        }else{
            DLinkedList node = map.get(key);
            if(isExpired(node)){
                removeOne(node);
                map.remove(key);
                size--;
                return -1;
            }

            node.timeStamp = System.currentTimeMillis();
            removeOne(node);
            addToHead(node);
            return node.val;
        }
    }

    public void put(int key,int val){
        if(!map.containsKey(key)){
            DLinkedList newNode = new DLinkedList(key,val);
            addToHead(newNode);
            map.put(key,newNode);
            size++;
            if(size>capacity){
                DLinkedList oldNode = tail.prev;
                removeOne(oldNode);
                map.remove(oldNode.key);
                size--;
            }
        }else {
            DLinkedList newNode = new DLinkedList(key,val);
            DLinkedList oldNode = map.get(key);
            removeOne(oldNode);
            addToHead(newNode);
            map.put(key,newNode);
        }
    }

}

class Main{
    public static void main(String[] args) {
        LRUCache cache = new LRUCache(2, 1000); // 1秒TTL

        cache.put(1, 1);
        cache.put(2, 2);
        System.out.println(cache.get(1)); // 返回 1

        try {
            Thread.sleep(1500); // 等待1.5秒让数据过期
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(cache.get(1)); // 返回 -1(已过期)
        System.out.println(cache.get(2)); // 返回 -1(已过期)
    }
}
全部评论
mark
1 回复 分享
发布于 2025-09-02 15:58 江苏
上周面字节刚遇到过,咋全都这么爱考这题。。。8说了,我还在被狠狠横向
1 回复 分享
发布于 2025-08-18 11:15 辽宁
这题字节手撕我遇到过
点赞 回复 分享
发布于 2025-08-17 18:34 广东
忍耐王
点赞 回复 分享
发布于 2025-09-27 00:43 广东

相关推荐

04-13 11:21
已编辑
北京航空航天大学 Java
年份:2026月份:2月面试轮次:三面岗位:中间件研发/SRE专家难度:⭐⭐⭐⭐⭐面试回顾:“设计一个用于RocketMQ/Kafka的消息轨迹追踪与全链路诊断平台。目标:1)能对每秒百万级的消息生产/消费进行无侵入、低开销的轨迹采集;2)能还原任意一条消息的完整生命周期(从哪个Producer、经过哪些Topic/Queue、被哪个Consumer消费、处理成功/失败、耗时多久);3)当出现消息堆积、重复消费或丢失时,能快速定位瓶颈或异常节点。给出架构设计、数据采集方案、存储与查询引擎选型。”💡&nbsp;解析:这是一道“可观测性”领域的顶尖难题,将消息中间件与分布式追踪深度结合。它要求超越简单的监控报警,构建一个能进行事后复杂调查的“病历系统”,是SRE和中间件团队的核心能力。设计思路:应用业务场景:这是保障抖音电商下单、支付、库存扣减等核心链路最终一致性的生命线。当用户支付成功但订单未更新时,运维人员可以凭借支付中心发出的消息ID,在这个平台中快速查明:消息是否发出?是否成功存储到Broker?库存服务是否已消费?消费耗时多久?是否抛出了异常?从而在几分钟内定位是网络问题、代码BUG还是数据库故障。核心考点:分布式追踪原理(OpenTracing,&nbsp;OpenTelemetry)消息中间件(RocketMQ/Kafka)的客户端与Broker端原理海量日志/时序数据处理架构(ELK/EFK,&nbsp;ClickHouse)流式计算(Flink)在可观测性场景的应用低性能损耗的埋点设计与异步编程实践(避坑指南):采样率控制:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;全量采集在洪峰期可能压垮系统。必须支持动态采样(如1%采样率),并在发生错误时(如消费失败)自动提升该链路的采样率为100%,确保问题可被追踪。上下文传递:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;traceId必须在整个异步消息链路中传递,包括线程池切换、异步回调、跨服务RPC调用,否则链路会断裂。存储成本:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;轨迹数据量巨大,必须设计清晰的生命周期策略(热数据ES,温数据ClickHouse,冷数据归档到对象存储)。🚨&nbsp;趋势押题预测预测名称:基于消息轨迹的智能根因分析与自愈系统押题题目:“在上述轨迹追踪平台的基础上,设计一个智能根因分析与自愈系统。要求:1)系统能自动分析消息堆积、延迟增高的故障,通过关联&nbsp;metrics、trace、log&nbsp;数据,自动定位到具体的服务、代码方法或基础设施层(如网络、磁盘);2)在识别出已知模式(如某数据库慢查询导致消费阻塞)后,能自动执行预案(如扩容、重启消费者、流量调度);3)生成可读的故障分析报告。阐述如何实现多源数据关联、根因分析算法,以及安全自动化的边界。”押题依据:公开招聘需求:在BOSS直聘和拉勾网上,字节跳动2026年发布的“SRE”、“可观测性引擎研发”岗位中,超过70%&nbsp;的JD明确要求“有AIOps、智能运维、根因分析项目经验”或“熟悉OpenTelemetry标准”。这标志着运维正从“监控告警”向“智能诊断”演进。行业技术风向:**CNCF(云原生计算基金会)**&nbsp;在2025年的年度报告中,将“AIOps”和“可观测性”列为增长最快的两大技术领域。KubeCon&nbsp;2025&nbsp;上有多个议题专注于“Using&nbsp;eBPF&nbsp;and&nbsp;ML&nbsp;for&nbsp;Root&nbsp;Cause&nbsp;Analysis”。开源项目动态:SkyWalking、Elastic&nbsp;APM&nbsp;等主流APM项目在2025年均增加了机器学习检测异常的插件或集成。这证明智能分析已成为可观测性工具演进的下一站。官方技术发声:&nbsp;&nbsp;&nbsp;&nbsp;火山引擎在2026年初的“云原生日”活动中,发布了“可观测性套件”的升级,重点宣传了其“智能诊断”功能,表明这是字节对外的技术产品方向,必然驱动内部技术栈对齐和人才要求。押题逻辑理由:当前面试题考察的是构建可观测性的“数据采集与查询”能力,这是基础。而行业公开的技术趋势(CNCF报告)、人才市场的明确需求(招聘JD)、以及字节自身对外的产品发布(火山引擎智能诊断),三者共同且强烈地指向了下一个技术制高点:利用已收集的海量可观测性数据,通过算法实现自动、精准的故障定位与自愈。面试官通过此题,能筛选出不仅会搭建系统,更能思考如何让系统产生“智能”、直接赋能业务稳定性的顶尖候选人。押此题,是基于公开的招聘要求、行业共识与公司产品路线图的强关联推导。核心考点:AIOOps基本理念、多源数据关联分析、时间序列异常检测算法、故障模式库、自动化运维的安全边界。适配岗位:&nbsp;&nbsp;&nbsp;&nbsp;SRE专家、可观测性平台架构师、中间件研发。押中概率:&nbsp;&nbsp;&nbsp;&nbsp;【80%】&nbsp;(行业明确趋势+招聘需求显性化+内部技术产品化)//&nbsp;【代码示例】基于简单规则的根因模式识别器(概念示例)@Componentpublic&nbsp;class&nbsp;RootCauseAnalyzer&nbsp;{@Autowiredprivate&nbsp;MetricService&nbsp;metricService;@Autowiredprivate&nbsp;TraceService&nbsp;traceService;@Autowiredprivate&nbsp;IncidentRepository&nbsp;incidentRepo;public&nbsp;Optional&lt;Diagnosis&gt;&nbsp;analyze(Alert&nbsp;alert)&nbsp;{//&nbsp;1.&nbsp;获取关联时段内的多维数据Instant&nbsp;windowStart&nbsp;=&nbsp;alert.getFireTime().minusSeconds(300);Instant&nbsp;windowEnd&nbsp;=&nbsp;alert.getFireTime();//&nbsp;获取相关服务的延迟、错误率指标Map&lt;String,&nbsp;Double&gt;&nbsp;latencySpike&nbsp;=&nbsp;metricService.getTopNSpikes(&quot;service_latency&quot;,&nbsp;windowStart,&nbsp;windowEnd,&nbsp;5);//&nbsp;获取慢Trace样本List&lt;SlowTrace&gt;&nbsp;slowTraces&nbsp;=&nbsp;traceService.getSlowTraces(windowStart,&nbsp;windowEnd,&nbsp;10);//&nbsp;获取错误日志聚合List&lt;ErrorPattern&gt;&nbsp;errorPatterns&nbsp;=&nbsp;logService.getErrorPatterns(windowStart,&nbsp;windowEnd);//&nbsp;2.&nbsp;应用规则进行模式匹配&nbsp;(此处为简化示例,实际可能使用决策树或图算法)//&nbsp;规则A:&nbsp;如果某个服务S延迟飙升,且其下游依赖DB的慢查询比例同时飙升for&nbsp;(String&nbsp;spikedService&nbsp;:&nbsp;latencySpike.keySet())&nbsp;{List&lt;String&gt;&nbsp;downstreamDBs&nbsp;=&nbsp;getDownstreamResources(spikedService,&nbsp;&quot;DB&quot;);for&nbsp;(String&nbsp;db&nbsp;:&nbsp;downstreamDBs)&nbsp;{if&nbsp;(metricService.isSpiked(db&nbsp;+&nbsp;&quot;_query_duration&quot;,&nbsp;windowStart,&nbsp;windowEnd))&nbsp;{//&nbsp;匹配到“数据库慢查询导致服务延迟”模式return&nbsp;Optional.of(new&nbsp;Diagnosis(&quot;DB_PERF_ISSUE&quot;,String.format(&quot;服务[%s]延迟由数据库[%s]慢查询导致&quot;,&nbsp;spikedService,&nbsp;db),List.of(new&nbsp;Action(&quot;SCALE_DB&quot;,&nbsp;db),&nbsp;new&nbsp;Action(&quot;RESTART_CONSUMER&quot;,&nbsp;spikedService))));}}}//&nbsp;规则B:&nbsp;如果错误日志中频繁出现“ConnectionTimeout”,且对应主机网络指标异常//&nbsp;...&nbsp;其他规则return&nbsp;Optional.empty();&nbsp;//&nbsp;无法自动诊断}}宝子们,字节跳动真题和押题预测都给你们整理好了,赶紧【关注】评论、收藏起来好好准备,祝大家都能顺利上岸!💪~~~关注/评论区:接好运~~~~~~上岸~!
查看2道真题和解析
点赞 评论 收藏
分享
04-13 19:12
已编辑
门头沟学院 Java
1.面试官业务介绍5-10min,然后说岗位跟面试邀约的可能不一样2.看你简历投大模型岗位,这边是后端岗多些,和统计更多,基础也比较重要3.反问ai结合场景这里莫名其妙的说了下,未来ai业务场景的的发展,最近看裁员帖子之类的面:像工程项目会被替代很多,像统计和类似于这种,系统验证还好些4.手撕回溯&nbsp;子集输入调错5.有看过限流算法吗;手撕&nbsp;令牌通限流服务端&nbsp;伪代码,加并发控制,加乒乓球式限流,还是流式限流;5.1&nbsp;怎么记录每个getToken()方法入参的lasttime构造器5.2&nbsp;怎么控制乒乓球式还是流式5.3&nbsp;&nbsp;refillToken方法要传什么参5.4&nbsp;gettoken&nbsp;没有写currentToken&nbsp;--5.5&nbsp;now&nbsp;-&nbsp;last&nbsp;时,单位是&nbsp;s、ms&nbsp;还是&nbsp;μs?用户体量比较大,百万的时候怎么考虑int&nbsp;会强转为&nbsp;0”,时间戳溢出&nbsp;+&nbsp;精度丢失问题。核心问题二:浮点数精度丢失与性能损耗me:基础有待提升面:思路还可以,细节有待提升,还是细节注意6.反问to&nbsp;B&nbsp;to&nbsp;C业务ai答案:如果是流式控制:我关注的是平均速率。我会利用令牌桶算法,重点调节&nbsp;refillRate(补充速率)。无论请求是突发还是连续,我都会把它们看作连续的数据流,只要桶里有令牌就放行,主要用于防止下游被大流量冲垮。如果是乒乓球式控制:我关注的是交互的同步性。这通常用于对延迟敏感或需要严格顺序的场景。我会通过信号量(Semaphore)或者容量为1的令牌桶来实现。核心逻辑是:必须收到上一个响应(回球),才释放下一个请求的令牌(发球)。所以,在代码里,我是通过选择限流原语(是用单纯的令牌桶,还是用信号量/状态机)来控制这两种模式的。”
查看8道真题和解析
点赞 评论 收藏
分享
评论
3
15
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务