编程大师-技术-算法-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次调用的约束。
相关推荐
_OP_CHEN9 小时前
【算法基础篇】(五十八)线性代数之高斯消元法从原理到实战:手撕模板 + 洛谷真题全解
线性代数·算法·蓝桥杯·c/c++·线性方程组·acm/icpc·高斯消元法
YGGP9 小时前
【Golang】LeetCode 1. 两数之和
leetcode
唐梓航-求职中9 小时前
编程大师-技术-算法-leetcode-355. 设计推特
算法·leetcode·面试
少许极端9 小时前
算法奇妙屋(二十八)-递归、回溯与剪枝的综合问题 1
java·算法·深度优先·剪枝·回溯·递归
仰泳的熊猫9 小时前
题目1453:蓝桥杯历届试题-翻硬币
数据结构·c++·算法·蓝桥杯
唐梓航-求职中9 小时前
技术-算法-leetcode-1606. 找到处理最多请求的服务器(易懂版)
服务器·算法·leetcode
啊阿狸不会拉杆9 小时前
《机器学习导论》第 10 章-线性判别式
人工智能·python·算法·机器学习·numpy·lda·线性判别式
会叫的恐龙9 小时前
C++ 核心知识点汇总(第11日)(排序算法)
c++·算法·排序算法
twilight_4699 小时前
机器学习与模式识别——线性回归算法
算法·机器学习·线性回归