leetcode
leetcode 1351 ~ 1400
设计浏览器历史记录

设计浏览器历史记录

难度:

标签:

题目描述

代码结果

运行时间: 236 ms, 内存: 17.3 MB


/* 
 * 思路:使用一个列表来存储浏览历史,并使用一个指针来表示当前页面的位置。
 * 当访问一个新页面时,将当前页面之后的所有历史记录删除,并将新页面添加到历史记录中。
 * 当后退时,将指针向左移动,直到到达最左边或达到步数要求。
 * 当前进时,将指针向右移动,直到到达最右边或达到步数要求。
 * 使用Java Stream来处理列表的操作。
 */

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class BrowserHistory {
    private List<String> history;
    private int currentIndex;

    public BrowserHistory(String homepage) {
        history = new ArrayList<>();
        history.add(homepage);
        currentIndex = 0;
    }

    public void visit(String url) {
        // 删除当前页面之后的所有历史记录并添加新页面
        history = history.stream().limit(currentIndex + 1).collect(Collectors.toList());
        history.add(url);
        currentIndex++;
    }

    public String back(int steps) {
        currentIndex = Math.max(0, currentIndex - steps);
        return history.get(currentIndex);
    }

    public String forward(int steps) {
        currentIndex = Math.min(history.size() - 1, currentIndex + steps);
        return history.get(currentIndex);
    }
}

解释

方法:

该题解使用一个列表来保存浏览器的历史记录,并使用一个整数索引来标记当前页面的位置。当访问新的网站时,它将从历史记录中删除当前索引之后的所有记录,然后添加新的记录并更新索引。后退操作会根据给定的步数减少索引,但不允许索引小于0。前进操作会根据给定的步数增加索引,但不允许索引超过历史记录的长度。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在`back`和`forward`函数中,当步数超过了可行的最大值时,代码直接将索引调整到边界值。这种处理方式是否会在某些情况下导致用户体验问题?例如,用户是否能够明确知道实际后退或前进了多少步?
是的,这种处理方式可能会导致用户体验问题。当步数超过可行的最大值时,用户实际后退或前进的步数会少于请求的步数,但是从现有的输出中,用户无法得知实际移动了多少步。为了改善用户体验,可以在方法中添加返回信息,说明实际移动的步数,或者在用户界面上提供反馈,告知用户超出的步数没有执行。
🦆
题解使用了普通的列表来存储浏览历史,是否考虑过使用其他数据结构(如双端队列)来优化某些操作的性能?
使用双端队列(deque)确实可以优化某些操作的性能。例如,使用deque可以更高效地从历史记录的前端或后端添加或删除元素,因为deque支持O(1)时间复杂度的插入和删除操作。在当前的实现中,每次调用`visit`函数时删除索引之后的元素是一个O(n)的操作,使用deque可以改进这一性能。然而,对于本题的具体需求,考虑到通常浏览历史记录不会非常长,使用列表也能满足性能需求,且实现较为简单。
🦆
在浏览器历史记录的实现中,如何处理异常情况,例如输入的`steps`参数为负数或极大值的情况?
在实际实现中,应该对`steps`参数进行有效性验证。如果`steps`为负数,应该抛出一个异常或返回一个错误信息,因为后退或前进的步数为负是不合逻辑的。对于极大值,虽然代码已经通过调整索引到边界值来处理,但更好的做法是在接收到异常大的`steps`值时,通过日志记录或异常处理机制来监控这种情况,以便开发者了解可能存在的错误或滥用行为。

相关问题