LeetCode 1472. Historial del navegador de diseño (Edición de Javascript) | Por Anisha Jain | enero, 2023
Un desafío de entrevista difícil común visto en las principales empresas
Implemente la clase BrowserHistory: BrowserHistory(string homepage) Inicializa un objeto con la página de inicio del navegador. void visit(string url) Visita la url desde la página actual. Aclara todo el historial de progreso. string back(int steps) Retrocede pasos en el historial. Si solo puede devolver x pasos y > x pasos en el historial, solo devolverá x pasos. Devuelve la URL actual después de retroceder en el historial con la mayor cantidad de pasos. string forward(int steps) Mueve los pasos hacia adelante en la historia. Si solo puedes avanzar x pasos y pasos > x en el historial, solo avanzarás x pasos. Devuelve la URL actual después de que la mayoría de los pasos se hayan redirigido al historial. Leetcode
Input:
["BrowserHistory","visit","visit","visit","back","back","forward","visit","forward","back","back"]
[["leetcode.com"],["google.com"],["facebook.com"],["youtube.com"],[1],[1],[1],["linkedin.com"],[2],[2],[7]]
Output:
[null,null,null,null,"facebook.com","google.com","facebook.com",null,"linkedin.com","google.com","leetcode.com"]
Este problema describe una clase llamada “BrowserHistory” que simula la función de historial de un navegador web. La clase tiene tres métodos:
BrowserHistory(string homepage)
: Este método es el constructor de la clase e inicializa el objeto con la página de inicio del navegador. Establece la URL actual en la página de inicio e inicializa dos listas, una para el historial de las URL visitadas (historial anterior) y otra para las URL desde las que se ha navegado (historial anterior).void visit(string url)
: Este método se llama cuando el usuario visita una nueva URL. Borra el historial de avance y agrega la nueva URL al historial de retroceso. La URL actual se establece en la nueva URL.string back(int steps)
: Este método se llama cuando el usuario quiere retroceder en el historial. El número de pasos para retroceder se toma como argumento. Si el usuario desea retroceder más pasos de los que están disponibles en el historial, el método retrocederá el máximo número de pasos posible. La URL actual se actualiza con la URL obtenida después de volver al historial.string forward(int steps)
: Este método se llama cuando el usuario quiere avanzar en la fecha. Se toma como argumento el número de pasos a seguir. Si el usuario desea avanzar más pasos de los disponibles en la fecha, el método avanzará el máximo número de pasos posibles. La URL actual se actualiza con la URL obtenida después de avanzar en el historial.
Esta clase debe realizar un seguimiento de las URL visitadas, permitir al usuario avanzar y retroceder en el historial y poder devolver la URL actual en cualquier momento.
Veamos una solución paso a paso utilizando la programación orientada a objetos.
Constructor
En un navegador, podemos ir y venir. Para lograr esto, debemos monitorearnos a nosotros mismos fecha anterior y el nuestro fecha de reenvío.
/**
* @param {string} homepage
*/
var BrowserHistory = function(homepage) {
this.history = [homepage]
this.forwardHistory = []
};
Visita la URL
Cuando visitamos una nueva url, el navegador borra todo nuestro historial de navegación. Si ha regresado anteriormente 5 veces y luego visitó una URL completamente nueva, no puede volver a las URL a las que regresó anteriormente.
Digamos que ha iniciado sesión en Google, Apple y luego en Medium en ese orden, ahora su historia de fondo [“Google”, “Apple”, “Medium”]. Ahora supongamos que ha vuelto a hacer clic dos veces, por lo que ahora estará en Google y su historial de reenvío ahora será [“Apple”, “Medium”] y tendrías una historia de fondo [“Google”]. Si ahora está visitando la nueva URL de YouTube, no puede continuar porque es un camino nuevo y aún no ha regresado. Entonces ahora su fecha de avance estaría vacía y su fecha de regreso estaría vacía [“Google”, “YouTube”].
¡Puede probar el ejemplo anterior en su navegador!
/**
* @param {string} url
* @return {void}
*/
BrowserHistory.prototype.visit = function(url) {
this.history.push(url)
if (this.forwardHistory.length > 0) {
this.forwardHistory = []
}
};
Retrocede unos pasos
Cada vez que regresamos, agregamos la URL a nuestro historial de reenvío tal como la eliminamos de nuestro historial de reversa. La parte complicada aquí es si alguien volvió a hacer clic más veces que las URL almacenadas en nuestro backlog. Supongamos que tenemos [“Google”, “Apple”] es nuestra historia de fondo, pero alguien vuelve a hacer clic 5 veces. Solo podemos retroceder dos veces, por lo que tenemos que llevarlos a Google, que tiene un historial de reenvío. [“Apple”].
Considere el siguiente código y comentarios para comprender las alternativas:
/**
* @param {number} steps
* @return {string}
*/
BrowserHistory.prototype.back = function(steps) {
// Initializing this variable is important because we are altering
// the length of the array in the loop and it will affect
// our i < value check at each iteration
const l = this.history.length - 1
// Taking the min of steps or l will handle our edge case
// for steps > items in history
for (let i = 0; i < Math.min(steps, l); i++) {
let b = this.history.pop()
this.forwardHistory.push(b)
}
// Be sure not to use the above initialized variable "l" here
// because the length is now different
return this.history[this.history.length - 1]
};
Otra nota rápida aquí: en el caso de Pasos> elementos, solo queremos eliminar la longitud: 1 elemento de la matriz de fechas para que podamos mostrar el último elemento en la fecha. Nuestra construcción de objetos permite que el último elemento del historial sea la página actual del usuario.
Da unos pasos hacia adelante
Al avanzar, el usuario solo puede hacer clic en avanzar hasta la longitud del Historial de avance. Si la fecha de avance tiene 2 elementos, solo podemos permitir pasos ≤ 2. Nuevamente usaremos pasos y longitud mínimos para satisfacer esta condición de borde. Otra cosa a tener en cuenta aquí es que en el cuadro de pasos> longitud para la fecha de avance podemos extraer cada elemento de la fecha de avance y agregarlo a la fecha de retroceso. Esto se debe a que la página actual del usuario se encuentra al final de la matriz de historial en nuestra configuración.
/**
* @param {number} steps
* @return {string}
*/
BrowserHistory.prototype.forward = function(steps) {
const l = this.forwardHistory.length
if (l > 0) {
for (let i = 0; i < Math.min(steps, l); i++) {
let b = this.forwardHistory.pop()
this.history.push(b)
}
}
return this.history[this.history.length - 1]
};
A menudo, para comprender mejor mi código, agrego notas a cada paso para ver cómo se actualiza cada uno de nuestros valores de variables durante las llamadas a funciones. Recomiendo las siguientes notas para que tu código funcione:
/**
* @param {string} homepage
*/
var BrowserHistory = function(homepage) {
this.history = [homepage]
this.forwardHistory = []
};/**
* @param {string} url
* @return {void}
*/
BrowserHistory.prototype.visit = function(url) {
// console.log(`visit "${url}"`)
this.history.push(url)
if (this.forwardHistory.length > 0) {
this.forwardHistory = []
}
// console.log(`history: "${this.history}"`)
// console.log(`forward: "${this.forwardHistory}"`)
};
/**
* @param {number} steps
* @return {string}
*/
BrowserHistory.prototype.back = function(steps) {
// console.log(`back ${steps} steps`)
// console.log(this.history.length - 1, Math.min(steps, this.history.length - 1))
const l = this.history.length - 1
for (let i = 0; i < Math.min(steps, l); i++) {
let b = this.history.pop()
// console.log(`Popped ${b} from history`)
this.forwardHistory.push(b)
}
// console.log(`history: "${this.history}"`)
// console.log(`forward: "${this.forwardHistory}"`)
// console.log(`return: "${this.history[this.history.length - 1]}"`)
return this.history[this.history.length - 1]
};
/**
* @param {number} steps
* @return {string}
*/
BrowserHistory.prototype.forward = function(steps) {
// console.log(`forward ${steps} steps`)
const l = this.forwardHistory.length
if (l > 0) {
for (let i = 0; i < Math.min(steps, l); i++) {
let b = this.forwardHistory.pop()
this.history.push(b)
}
}
// console.log(`history: "${this.history}"`)
// console.log(`forward: "${this.forwardHistory}"`)
// console.log(`return: "${this.history[this.history.length - 1]}"`)
return this.history[this.history.length - 1]
};
/**
* Your BrowserHistory object will be instantiated and called as such:
* var obj = new BrowserHistory(homepage)
* obj.visit(url)
* var param_2 = obj.back(steps)
* var param_3 = obj.forward(steps)
*/