编程大师-技术-算法-leetcode-1472. 设计浏览器历史记录

你需要实现一个模拟单标签页浏览器历史记录的 BrowserHistory 类,核心要求是高效处理访问新页面(清空前进记录)、后退、前进 三个操作。最适合的方案是用 ArrayList 存储历史记录,配合当前索引定位,所有操作的时间复杂度均为 O(1)(visit 截断操作最坏 O(n),但题目约束下完全够用),且逻辑直观、易于理解。

解题思路

  1. 数据结构选择

    • ArrayList<String> 存储浏览历史(按访问顺序排列),支持随机访问和快速截断;
    • int current 记录当前所在页面的索引(初始为0,对应首页)。
  2. 核心操作逻辑

    操作 实现方式
    初始化 将首页加入历史列表,current 设为0。
    visit(url) 截断 current 之后的所有历史记录(清空前进记录),添加新url,current 移到新索引。
    back(steps) 计算新索引 = Math.max(0, current - steps)(不超过历史起点),更新 current 并返回对应url。
    forward(steps) 计算新索引 = Math.min(history.size()-1, current + steps)(不超过历史终点),更新 current 并返回对应url。

完整Java代码(AC级性能,匹配示例)

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class BrowserHistory {
    // 存储浏览历史记录(按访问顺序)
    private final List<String> history;
    // 当前页面在history中的索引
    private int current;

    // 初始化:首页作为初始历史记录
    public BrowserHistory(String homepage) {
        history = new ArrayList<>();
        history.add(homepage);
        current = 0;
    }

    // 访问新url,清空前进记录
    public void visit(String url) {
        // 步骤1:删除current之后的所有记录(前进记录清空)
        // 比如当前在索引2,历史有[0,1,2,3,4],则删除3、4,保留[0,1,2]
        if (current < history.size() - 1) {
            history.subList(current + 1, history.size()).clear();
        }
        // 步骤2:添加新url,current移到新索引
        history.add(url);
        current = history.size() - 1;
    }

    // 后退steps步,返回最终页面url
    public String back(int steps) {
        // 计算后退后的索引(不能小于0)
        current = Math.max(0, current - steps);
        return history.get(current);
    }

    // 前进steps步,返回最终页面url
    public String forward(int steps) {
        // 计算前进后的索引(不能超过历史记录最后一位)
        current = Math.min(history.size() - 1, current + steps);
        return history.get(current);
    }

    // 测试用例(匹配题目示例)
    public static void main(String[] args) {
        BrowserHistory browserHistory = new BrowserHistory("leetcode.com");
        browserHistory.visit("google.com");     // history: [leetcode, google], current=1
        browserHistory.visit("facebook.com");   // history: [leetcode, google, facebook], current=2
        browserHistory.visit("youtube.com");    // history: [leetcode, google, facebook, youtube], current=3
        System.out.println(browserHistory.back(1)); // 3-1=2 → facebook.com
        System.out.println(browserHistory.back(1)); // 2-1=1 → google.com
        System.out.println(browserHistory.forward(1)); // 1+1=2 → facebook.com
        browserHistory.visit("linkedin.com");   // 截断current=2之后的youtube,添加linkedin → history: [leetcode, google, facebook, linkedin], current=3
        System.out.println(browserHistory.forward(2)); // 3+2=5,但最大是3 → linkedin.com
        System.out.println(browserHistory.back(2)); // 3-2=1 → google.com
        System.out.println(browserHistory.back(7)); // 1-7=-6 → 0 → leetcode.com
    }
}

代码关键部分解释

  1. visit方法的截断逻辑
    • history.subList(current + 1, history.size()).clear()subList 返回的是原列表的视图,clear() 会直接删除原列表中对应范围的元素,高效清空前进记录;
    • 例如当前在索引2(facebook),访问linkedin时,会删除索引3(youtube),再添加linkedin,确保前进记录被清空。
  2. 索引边界处理
    • back 时用 Math.max(0, ...) 确保不后退到首页之前;
    • forward 时用 Math.min(history.size()-1, ...) 确保不前进到未访问的页面。
  3. 性能保障
    • ArrayListget 是 O(1) 随机访问,subList().clear() 是 O(n)(n为截断的元素数),但题目中最多调用5000次方法,且单次截断的元素数有限,实际运行无性能问题。

测试用例执行结果(匹配题目输出)

复制代码
facebook.com
google.com
facebook.com
linkedin.com
google.com
leetcode.com

进阶优化(可选,针对极端场景)

如果需要支持百万级历史记录visit 频繁截断,可改用 LinkedList + 迭代器,但会牺牲随机访问性能。对于题目给定的约束(最多5000次调用),ArrayList 是最优选择。

总结

  1. 核心数据结构:ArrayList 存储历史记录 + 索引定位当前页面,兼顾随机访问和截断效率;
  2. 关键逻辑:visit 时截断前进记录,back/forward 时严格控制索引边界;
  3. 性能:所有操作均为高效操作,完全满足题目5000次调用的约束。
相关推荐
心中有国也有家11 小时前
cann-recipes-infer:昇腾 NPU 推理的“菜谱集合”
经验分享·笔记·学习·算法
绝知此事11 小时前
【算法突围 01】线性结构与哈希表:后端开发的收纳术
java·数据结构·算法·面试·jdk·散列表
碧海银沙音频科技研究院11 小时前
通话AEC与语音识别AEC的软硬回采链路
深度学习·算法·语音识别
csdn_aspnet12 小时前
Python 算法快闪 LeetCode 编号 70 - 爬楼梯
python·算法·leetcode·职场和发展
m0_6294947314 小时前
LeetCode 热题 100-----26.环形链表 II
数据结构·算法·leetcode·链表
壹号用户14 小时前
用队列实现栈
数据结构·算法
做人求其滴15 小时前
面试经典 150 题 380 274
c++·算法·面试·职场和发展·力扣
daad77715 小时前
记一组无人机IMU传感器数据
算法
计算机安禾15 小时前
【c++面向对象编程】第42篇:模板特化与偏特化:为特定类型定制实现
开发语言·c++·算法