Preguntas frecuentes sobre estructuras de datos y algoritmos (actualizadas continuamente...)

1. cuerda


1. Descripción de la transformación de cadena : para una cadena con una longitud de n, debemos realizar algunas transformaciones en ella.
Primero, esta cadena contiene algunos espacios, como "Hola mundo", y luego lo que debemos hacer es invertir el orden de las palabras separadas por espacios en esta cadena e invertir el caso de cada carácter al mismo tiempo.
Entrada del ejemplo 1
:
"Esta es una muestra",
valor de retorno 16:
"La MUESTRA A ES ESTA"

// 思路:
// 1. 将字符串用split(' ')按照空格符分割成数组
// 2. 将数组翻转,判断每一个项中每一个字母的大小写,如果是大写改为小写,如果是小写改为大写,生成一个新数组
// 3. 将新数组用join拼接成一个字符串
// 4. 注意:
//    split():默认按照空格分隔,会把多个空格当成一个分隔符。
//    split(' '):按照空格分隔,会把每一个空格都当成一个分隔符。
//    split(''):将每一个字符串都分隔。
const str = 'Hello World This Is a Student'
function trans(str, num){
    
    
  if(str.length != num)return '数组的长度有误!'
  const arrReverse = str.split(' ').reverse()
  return arrReverse.map(item => {
    
    
    // 进行大小写的转换
    return [...item].map(ele => ele == ele.toLowerCase() ? ele.toUpperCase() : ele.toLowerCase()).join('')
  }).join(' ')
}
console.log(trans(str,29))  // sTUDENT A iS tHIS wORLD hELLO


2. Descripción del prefijo común más largo de cadenas : se le proporciona una matriz de cadenas de tamaño n, que contiene n cadenas, escribe una función para encontrar el prefijo común más largo en la matriz de cadenas y devuelve este prefijo común.
Ejemplo 1
Entrada: ["abc"]
Valor de retorno: "abc"
Ejemplo 2
Entrada: ["abca", "abc", "abca", "abc", "abcc"]
Valor de retorno: "abc"

// 思路:
// 1. 如果数组长度为0,则返回空字符串
// 2. 如果数组长度为1,则返回数组中的字符串
// 3. 将数组排序,用第一个元素的第一个字符和最后一个元素的第一个字符进行比较
// 4. 如果相同将这个字符保存下来,以此类推将每次的字符串拼接起来,直到比较的两个字符串不相同,终止循环,最后返回拼接后的字符串
const strArr = ["abca","abc","abca","abc","abcc"]
function longestCommonPrefix(strArr){
    
    
  if(!strArr.length) return ''
  if(strArr.length === 1) return strArr[0]
  strArr.sort()
  const firstStr = strArr[0]
  const lastStr = strArr.pop()
  let res = ''
  for(let i=0;i<firstStr.length;i++){
    
    
    if(firstStr[i] == lastStr[i]){
    
    
      res += firstStr[i]
    }else{
    
    
      break
    }
  }
  return res
}

3. Verifique la
descripción de la dirección IP : dada una dirección IP, determine si es una dirección IP4 o una dirección IP6.

Una dirección IPv4 está representada por cuatro grupos de números decimales y puntos, cada dirección contiene 4 números decimales que van del 0 al 255, separados por (“.”). Por ejemplo, 172.16.254.1;
al mismo tiempo, el número en la dirección IPv4 no comenzará con 0. Por ejemplo, la dirección 172.16.254.01 es ilegal.

Una dirección IPv6 está representada por 8 grupos de números hexadecimales y cada grupo representa 16 bits. Estos grupos de números están separados por (":"). Solo se admiten caracteres en mayúsculas y minúsculas y números del 0 al 9, no se permiten caracteres especiales ni espacios.

Ejemplo 1
Entrada: "172.16.254.1"
Valor de retorno: "IPv4"
Explicación: Esta es una dirección IPv4 válida, por lo tanto, devuelva "IPv4"

Ejemplo 2
Entrada: "2001:0db8:85a3:0:0:8A2E:0370:7334"
Valor de retorno: "IPv6"
Explicación: Esta es una dirección IPv6 válida, por lo tanto, devuelva "IPv6"

Ejemplo 3
Entrada: "256.256.256.256"
Valor de retorno: "Ninguno"
Explicación: Esta dirección no es ni IPv4 ni IPv6

// 思路:
// 1. 对输入的字符串先判断是属于ipv4范畴的还是ipv6范畴的
// 2. 如果属于ipv4范畴进行ipv4的判定,如果属于ipv6范畴进行ipv6判定。否则直接返回 Neither
// 3. 对于ipv4的判定:
//   (1)先使用split('.')分割成数组,对数组长度判断,如果长度不为4,则返回 Neither。否则对数组里面的每一项是一个字符串进行判断
//   (2)如果字符串长度为0或者大于3则返回false,否则对字符串每一项判断
//   (3)如果字符串的第一项是'0'则返回false,否则如果不在'0'和'9'之间也返回false
//    (4) 将这个字符串转成数字,如果不在0-255之间返回false,否则返回true
// 4. 对于ipv6的判定:
//    (1) 先试用split(':')分割成数组,对数组长度判断,如果长度不为8,则返回 Neither,否则对数组里面的每一项是一个字符串进行判断
//    (2) 如果字符串长度为0或者大于4则返回false,否则对字符串每一项判断
//   (3)如果每一项的字符不在'0'--'9'、 'a'--'z' 、 'A'--'Z'之间则返回false,否则返回true

// 定义判断ipv4的方法:
function checkIPv4(s){
    
    
  if(s.length === 0 || s.length > 3) return false
  if(s[0] === '0') return false
  for(let i of s){
    
    
    if(i > '9' || i < '0') return false
  }
  return Number(s) <= 255 && Number(s) > 0
}

// 定义判断ipv6的方法:
function checkIPv6(s){
    
    
  if(s.length === 0 || s.length > 4) return false
  for(let j of s){
    
    
    if(!(j>='0' && j<='9' || j>='a' && j<='f' || j>='A' && j<='F')) return false
  }
  return true
}

function solve(IP){
    
    
  if(IP.indexOf('.') != -1){
    
    
    const arrIpv4 = IP.split('.')
    if(arrIpv4.length != 4) return 'Neither'
    for(let ip of arrIpv4){
    
    
      if(!checkIPv4(ip)){
    
    
        return 'Neither'
      }
    }
    return 'IPv4'
  }else if(IP.indexOf(':') != -1){
    
    
    const arrIpv6 = IP.split(':')
    if(arrIpv6.length != 8) return 'Neither'
    for(let ip of arrIpv6){
    
    
      if(!checkIPv6(ip)){
    
    
        return 'Neither'
      }
    }
    return 'IPv6'
  }else{
    
    
    return 'Neither'
  }
}


4. Descripción de la suma de números grandes : lea dos números en forma de cadena, escriba una función para calcular su suma y devuélvala en forma de cadena.
Rango de datos : la longitud es menor o igual a 100000 y la cadena solo se compone de '0'-'9'
Requisitos : complejidad del tiempo O (n)

Ejemplo 1
Entrada: "1", "99"
Valor de retorno: "100"
Explicación: 1+99=100

Ejemplo 2
de entrada: "114514", ""
valor de retorno: "114514"

// 思路:
// 1. 对于一个很大的数来说不可以直接采用 Number()转成数字再相加,再用String(),因为这时候会丢失精度
// 2. 当两个数位数不一样的时候,分割成数组,在小的那个数前面补位'0',直到对齐
// 3. 从后往前加,做进位处理。如果大于9,则取余数,将余数用unshift()放进一个空数组的前面。同时记录一个变量为1。下次相加的时候加上这个变量
//    如果不大于9,则将这个数放进数组的前面
// 4. 最后将得到的数组用join()方法拼接成一个字符串
function solve(s,t){
    
    
  const arr1 = s.split('')
  const arr2 = t.split('')
  let resArr = [], go = 0
  while(arr1.length || arr2.length){
    
    
    let num1 = +arr1.pop() || 0
    let num2 = +arr2.pop() || 0
    let temp = num1 + num2 + go
    if(temp > 9){
    
    
      temp %= 10
      go = 1
    }else{
    
    
      go = 0
    }
    resArr.unshift(temp)
  }
  if (go) resArr.unshift(1);
  return resArr.join('')
}

2. Montón, pila, cola

1. Use dos pilas para implementar
la descripción de la cola: use dos pilas para implementar una cola y use n elementos para completar la función de insertar un número entero (push) al final de la cola n veces y eliminar un número entero (pop) en el cabeza de la cola n veces. Los elementos de la cola son de tipo int. Asegúrese de que la operación sea legal, es decir, asegúrese de que haya elementos en la cola cuando se realice la operación pop.
Rango de datos : n<=1000
Requisitos : La complejidad espacial de almacenar n elementos es O(n), y la complejidad temporal de la inserción y eliminación es O(1)
Ejemplo 1
Entrada: ["PSH1", "PSH2", " POP ", "POP"]
Valor de retorno: 1, 2
Descripción: BinarySearchTree
"PSH1": representa insertar 1 al final de la cola
"PSH2": representa insertar 2 al final de la cola
"POP": representa eliminar un elemento, primero en entrar, primero en salir => Devuelve 1
"POP": significa eliminar un elemento, primero en entrar, primero en salir => devuelve 2

// 方法一:
// 思路:
// 1. 定义两个空栈
// 2. 将数字push进第一个栈,然后再将pop出来的值push进第二个栈。最后在pop出来
// let arr2 = [],
//       arr1 = [];
// function push(node)
// {
    
    
//     // write code here
//     arr1.push(node);
// }
// function pop()
// {
    
    
//     // write code here
//     if(!arr2.length){
    
    
//         while(arr1.length){
    
    
//             arr2.push(arr1.pop())
//         }
// }
//         return arr2.pop();
// }

// 方法二:
// 思路:
// 1. 定义一个空栈
// 2. 先将值push进去,然后再shift从头部删除值
let queue = [];
function push(node)
{
    
    
  return queue.push(node);
}
function pop()
{
    
    
  return queue.shift();
}


2. Descripción de la pila , incluida la función Min : defina la estructura de datos de la pila, implemente una función min en este tipo que pueda obtener el elemento más pequeño contenido en la pila y asegúrese de que cuando las funciones pop, top y min se operen durante Para operaciones de entrada, debe haber una cierta cantidad de elementos en la pila.

Los métodos contenidos en esta pila son:
push(value): inserta el valor en la pila
pop(): extrae el elemento superior de la pila
top(): obtiene el elemento superior de la pila
min(): obtiene el elemento más pequeño de la pila pila

Ejemplo :
Entrada: ["PSH-1", "PSH2", "MIN", "TOP", "POP", "PSH1", "TOP", "MIN"] Salida: -1,2,1,
-1
Análisis:
"PSH-1" significa empujar -1 en la pila y el elemento en la pila es -1
"PSH2" significa empujar 2 en la pila y el elemento en la pila es 2, -1
"MIN" significa obtener la pila en este momento El elemento más pequeño ==> devolver -1
"TOP" significa obtener el elemento superior de la pila ==> devolver 2
"POP" significa sacar el elemento superior de la pila, sacar 2, el elemento en la pila es -1
"PSH1" significa empujar 1 en la pila, el elemento en la pila es 1, -1
"TOP" significa obtener el elemento superior de la pila ==> devolver 1
"MIN" significa obtener el elemento más pequeño en la pila en este momento ==> devolver -1

// 思路:
// 1. 定义一个空栈
// 2. top函数获取的就是栈中最后一个元素
// 3. min函数获取就是栈中元素的最小值,可以使用Math.min()方法
let stack = []
function push(node)
{
    
    
  return stack.push(node)
}
function pop()
{
    
    
  if(stack.length){
    
    
    return stack.pop()
  }
}
function top()
{
    
    
  return stack[stack.length - 1]
}
function min()
{
    
    
  return Math.min(...stack)
}

3.
Descripción de secuencia de corchetes válida: Dada una cadena que contiene solo los caracteres '(',')','{','}','['y']', determine si la cadena dada es legal. La secuencia de corchetes, el El corchete debe cerrarse en el orden correcto, "()" y "()[]{}" son secuencias de corchetes legales, pero "(]" y "([)]" no son legales. Rango de datos: Longitud de cadena
0 < = n <= 10000
Requisitos : complejidad espacial O(n), complejidad temporal O(n)

Ejemplo 1
Entrada: "["
Valor de retorno: falso

Ejemplo 2
Entrada: "[]"
Valor de retorno: verdadero

// 思路:
// 1. 先判断字符串的长度是不是偶数,如果是奇数则一定匹配不成功直接返回false
// 2. 如果长度是偶数,定义一个空栈,从左往右遍历字符串,遇到左字符串则放进栈中
// 3. 继续遍历如果遇到右字符串立刻从栈中弹出一个字符串,如果二者不能匹配则返回false
// 4. 遍历结束后如果栈的长度为零则说明匹配成功,是有效括号序列,返回true
function isValid( s ) {
    
    
  const len = s.length % 2
  let stack = []
  if(len) return false
  for(let i of s){
    
    
    if(i=='(' || i=='[' || i=='{'){
    
    
      stack.push(i)
    }else{
    
    
      if(stack.length){
    
    
        if(i==')'){
    
    
          if(stack.pop() != '(') return false
        }else if(i==']'){
    
    
          if(stack.pop() != '[') return false
        }else{
    
    
          if(stack.pop() !='{') return false
        }
      }else{
    
    
        // 说明没有左括号,肯定匹配不成功
        return false
      }
    }
  }
  return !stack.length
}


4. Descripción del valor máximo de la ventana deslizante : dado un número de matriz de longitud n y el tamaño de la ventana deslizante, encuentre el valor máximo de todos los valores en la ventana deslizante.
Por ejemplo, dada la matriz [1,2,3], el tamaño de la ventana es 2. Entonces todos los resultados deslizantes pueden ser [1,2], [2,3], por lo que el valor máximo correspondiente es [2,3] Entrada
del ejemplo 1
: [2,3,4,2,6,2,5,1] ,3
valor de retorno: [4,4,6,6,6,5]

Ejemplo 2
de entrada: [9,10,9,-7,-3,8,2,-6], 5
valor de retorno: [10,10,9,8]

Ejemplo 3
de entrada: [1,2,3,4], 5
valor de retorno: []

// 方法一思路:
// 1. 判断窗口长度和数组长度的大小,窗口长度为0,或者数组长度为0,或者窗口长度大于数组长度,返回空数组
// 2. 确定可能出现的滑动结果即有几组值,n = len - size + 1(n:滑动窗口值,len:数组长度,size:窗口大小)
// 3. 遍历数组,记录所有的滑动窗口,并计算出每一个窗口中的最大值
// 4. 将记录的最大值push进入一个新的栈中,最后返回这个栈
function maxInWindows( num ,  size ) {
    
    
  if(!size || size > num.length) return []
  const endValue = num.length - size
  let maxNum = []
  let stack = []
  for(let i=0;i<endValue+1;i++){
    
    
    for(let j=i;j<i+size;j++){
    
    
      stack.push(num[j])
    }
    const max = Math.max(...stack)
    maxNum.push(max)
    stack = []
  }
  return maxNum
}

// 方法二思路:
// 1. 判断窗口长度和数组长度的大小,窗口长度为0,或者数组长度为0,或者窗口长度大于数组长度,返回空数组
// 2. 新建两个空栈 stack 和 maxNum 遍历数组将每一项放进 stack 中,判断 stack 的长度
//    如果 stack 的长度等于 size,此时求取 stack 中的最大值,放进 maxNum 中
//    如果 stack 的长度大于 size,此时从 stack 中删除第一个元素,此时 stack 的长度会等于 size,在求取 stack 中的最大值放进 maxNum 中
// 3. 遍历结束后返回 maxNum
function maxInWindows( num ,  size ){
    
    
  if(!num.length || !size || size > num.length) return []
  let stack = [],maxNum = []
  for(let i of num){
    
    
    stack.push(i)
    if(stack.length > size){
    
    
      stack.shift()
    }
    if(stack.length == size){
    
    
      maxNum.push(Math.max(...stack))
    }
  }
  return maxNum
}


5. Descripción de los k números más pequeños : Dada una matriz de longitud n que puede tener valores duplicados, encuentre los k números más pequeños que no eliminan duplicados. Por ejemplo, los elementos de la matriz son 8 números 4, 5, 1, 6, 2, 7, 3, 8 y los 4 números más pequeños son 1, 2, 3, 4 (en cualquier orden).
Ejemplo 1
Entrada: [4,5,1,6,2,7,3,8],4
Valor de retorno: [1,2,3,4]
Explicación: Devuelve los 4 números más pequeños, devuelve [1, 3,2 ,4] también funciona

Ejemplo 2
entrada: [1], 0
valor de retorno: []

Ejemplo 3
de entrada: [0,1,2,1,2], 3
valor de retorno: [0,1,1]

// 思路:
// 1. 将数组从小到大排序
// 2. 新建一个空栈,从排序后的数组中 shift 出前 k 个数
function GetLeastNumbers_Solution(input, k){
    
    
  if(!input.length || !k) return []
  let stack = []
  input.sort((a,b) => a-b)  // 从小到大排个序,会改变原数组
  for(let i=0;i<k;i++){
    
    
    stack.push(input.shift())
  }
  return stack
}

6. Encuentre el késimo número más grande
Descripción : Hay una matriz de números enteros, busque el késimo número más grande en la matriz de acuerdo con la idea de clasificación rápida. Dada una matriz de enteros a, dado su tamaño n y la k que desea encontrar, devuelva el k-ésimo número más grande (incluidos los elementos repetidos, no es necesario eliminar duplicados) y asegúrese de que exista la respuesta

Ejemplo 1
entrada: [1,3,5,2,2],5,3
valor de retorno: 2

Ejemplo 2
Entrada: [10,10,9,9,8,7,5,6,4,3,4,2],12,3
Valor de retorno: 9
Explicación: El tercero más grande después de la deduplicación es 8, pero esta pregunta requiere elementos repetidos y no es necesario deduplicarlos, por lo que la salida 9

// 思路:
// 1. 先判断数组长度是否为零,数组长度和n,k的大小关系。如果数组长度为零,或者数组长度不等于n,或者小于k。都返回false
// 2. 将数组从大到小排列,从中取出第k个数
function findKth( a ,  n ,  K ) {
    
    
  if(!a.length || a.length != n || a.length < K ) return false
  a.sort((a,b) => b-a)  // 从大到小排列
  return a[K-1]
}

7. Encuentre la mediana
Descripción : / ¿Cómo obtener la mediana en un flujo de datos? Si se lee un número impar de valores del flujo de datos, la mediana es el valor en el medio de todos los valores ordenados. Si se lee un número par de valores del flujo de datos, la mediana es el promedio de los dos números del medio después de ordenar todos los valores.

Ejemplo 1
Entrada: [5,2,3,4,1,6,7,0,8]
Valor de retorno: "5,00 3,50 3,00 3,50 3,00 3,50 4,00 3,50 4,00 "
Explicación: El flujo de datos escupe continuamente 5,2, 3 ..., los promedios obtenidos son 5, (5+2)/2, 3...

Ejemplo 2
Entrada: [1,1,1]
Valor de retorno: "1,00 1,00 1,00 "

// 思路:
// 1. 如果是一个空数组,直接返回'',
// 2. 新建一个数组,把原数组中的头部元素逐一取出放进这个数组中。在放进之后对数组进行从小到大的排序,排序完对数组长度判断
//    如果长度是奇数,则取中间值。如果长度是偶数则取中间两个值的平均值,就是中位数
// 3. 将上面得到中位数再放进一个新的栈中
// 4. 用join(' ')的方法拼成一个字符串


// 读取数据流
function Insert(num)
{
    
    
  if(!num.length) return ''
  let stack1 = [],stack2 = []
  for(let i=0;i<num.length;i++){
    
    
    stack1.push(num[i]) // 取出num中的头部元素放进stack1中
    stack1.sort((a,b)=>a-b)  // 对stack1进行从小到大排序
    const median = GetMedian(stack1)
    stack2.push(median)
  }
  return stack2.join(' ')
}

// 获取当前数据流中的中位数
function GetMedian(arr){
    
    
	if(arr.length % 2){
    
    
    // 此时数组长度为奇数,中位数是中间的值
    const index = Math.floor(arr.length / 2)
    const value = arr[index]
    return value.toFixed(2)
  }else{
    
    
    // 此时数组长度是偶数,中位数是中间两个值的平均值
    const index = arr.length / 2
    const value = (arr[index] + arr[index - 1]) / 2
    return value.toFixed(2)
  }
}

8.
Descripción de la evaluación de expresiones : escriba una calculadora de números enteros que admita suma, resta, multiplicación y paréntesis.
Requisitos : Complejidad espacial: O (n), Complejidad temporal: O (n)

Ejemplo 1
Entrada: "1+2"
​​Valor de retorno: 3

Ejemplo 2
Entrada: "(2*(3-4))*5"
Valor de retorno: -10

Ejemplo 3
Entrada: "3+2 3 4-1"
Valor de retorno: 26

function solve( s ) {
    
    
  // write code here
  return eval(s)
}

3. hachís


1. Descripción de la suma de dos números : dados una matriz de números enteros y un valor objetivo objetivo, busque los subíndices de dos números que suman el valor objetivo en la matriz, y los subíndices devueltos se organizan en orden ascendente.
Requisitos : complejidad espacial O (n), complejidad temporal O (nlogn)

Ejemplo 1
Entrada: [3,2,4],6
Valor de retorno: [2,3]
Explicación: Porque 2+4=6, y el subíndice de 2 es 2, y el subíndice de 4 es 3, y porque el subíndice 2 <subíndice 3, entonces devuelve [2,3]

Ejemplo 2
Entrada: [20,70,110,150],90
Valor de retorno: [1,2]
Explicación: 20+70=90

function twoSum(numbers, target) {
    
    
  if(!numbers.length) return false
  const map = new Map()
  for(let i=0; i<numbers.length; i++) {
    
    
    if(map.has(target-numbers[i])) {
    
    
      return [map.get(target-numbers[i]) + 1, i + 1]
    }else {
    
    
      map.set(numbers[i], i)
    }
  }
}


2. Descripción de los números que aparecen más de la mitad del tiempo en la matriz : Dada una matriz de longitud n, hay un número en la matriz que aparece más de la mitad de la longitud de la matriz; encuentre este número.
Requisitos : complejidad espacial: O (1), complejidad temporal O (n)

Ejemplo 1
de entrada: [1,2,3,2,2,2,5,4,2]
valor de retorno: 2

Entrada del ejemplo 2
: [3,3,3,3,2,2,2]
valor de retorno: 3

Ejemplo 3
Entrada: [1]
Valor de retorno: 1

// 方法一思路:
// 1. 建立一个空对象,将数组中的每一项作为对象中的key,出现次数作为值。(利用了对象中key的唯一性)
// 2. 如果这个值第一次出现就将他的值设为1,后面再出现一次,就将这个值加上1。和数组长度的一半向下取值比较
// 3. 如果小于,继续循环;如果大于终止循环,返回当前的key

// 使用一般 for 循环
// const arr = [1,2]
function MoreThanHalfNum_Solution( numbers ) {
    
    
  const len = Math.floor(numbers.length / 2 )
  let obj = {
    
    }
  if(numbers.length == 1){
    
    
    return numbers[0]
  }else{
    
    
    for(let i of numbers){
    
    
      if(obj[i]){
    
    
        obj[i]++
        if(obj[i] > len){
    
    
          return i
        }
      }else{
    
    
        obj[i] = 1
      }
    }
    return '无解'
  }
} 
// console.log(MoreThanHalfNum_Solution(arr));

// 使用reduce
// const arr = [3,3,3,3,2,2,2]
function MoreThanHalfNum_Solution(numbers){
    
    
  const len = Math.floor(numbers.length / 2 )
	if(numbers.length == 1) return numbers[0]
	const obj = numbers.reduce((preValue,curValue)=>{
    
    
		preValue[curValue] = (preValue[curValue] + 1) || 1
		return preValue
	},{
    
    })
  for(let i in obj){
    
    
    if(obj[i] > len) return i
  }
  return '无解'
}
// console.log(MoreThanHalfNum_Solution(arr));

// // 方法二:思路
// 将数组从小到大排列,取中那个数
// 如果这个数在数组中出现次数超过了一半,则排序后中间的那个数就是要求的结果
const arr = [3,3,3,3,2,2,2]
function MoreThanHalfNum_Solution(numbers){
    
    
  const len = Math.floor(numbers.length / 2 )
  return numbers.sort((a,b) => a -b)[len]
}
console.log(MoreThanHalfNum_Solution(arr));


3. Descripción de dos números que solo aparecen una vez en una matriz : En una matriz de números enteros, excepto dos números que solo aparecen una vez, los demás números aparecen dos veces. Escriba un programa para encontrar estos dos números que aparecen solo una vez.
Requisitos : complejidad espacial O (1), complejidad temporal O (n), los resultados de salida están organizados en orden no descendente

Ejemplo 1
Entrada: [1,4,1,6]
Valor de retorno: [4,6]
Explicación: El número más pequeño en los resultados devueltos ocupa el primer lugar

Ejemplo 2
entrada: [1,2,3,3,2,9]
valor de retorno: [1,9]

// 方法一思路:
// 1. 新建一个对象 obj 和一个数组 arr
// 2. 将数组中的每一项作为对象中的key,出现次数作为值。(利用了对象中key的唯一性)
// 3. 统计每个数字出现的次数,然后对obj里面的每一项进行判断,如果对应的值为1,则将这个键放入arr数组中
// 4. 将最后得到的arr数组按照从小到大的顺序进行排列
function FindNumsAppearOnce(nums){
    
    
  let obj = {
    
    }, arr = []
  for(let i of nums){
    
    
    if(obj[i]){
    
    
      obj[i]++
    }else{
    
    
      obj[i] = 1
    }
  }
  for(let j in obj){
    
    
    if(obj[j] == 1){
    
    
      arr.push(+j)
    }
  }
  return arr.sort((a,b) => a-b)
}

// 方法二思路:
// 1. 新建一个数组 arr 用于存储返回的结果
// 2. 如果这个数字在数组中只出现了一次,那么从头开始找和从尾开始找得到的应该是同一个数组下标
// 3. 所以判断indexOf() 和 lastIndexOf() 返回的下标是否相同,如果相同将这个值 push 进入 arr 中
// 4. 将得到的数组按照从小到大的顺序排列
function FindNumsAppearOnce(nums){
    
    
  let arr = []
  for(let i of nums){
    
    
    if(nums.indexOf(i) == nums.lastIndexOf(i)){
    
    
      arr.push(i)
    }
  }
  return arr.sort((a,b) => a-b)
}


4. Descripción del primer entero positivo que falta : Dada una matriz de números enteros sin elementos repetidos, busque el entero positivo más pequeño que no aparezca en ella.
Requisitos : Complejidad espacial O (1), complejidad temporal O (n)

Ejemplo 1
Entrada: [1,0,2]
Valor de retorno: 3

Ejemplo 2
de entrada: [-2,3,4,1,5]
valor de retorno: 2

Ejemplo 3
entrada: [4,5,6,8,9]
valor de retorno: 1

// 思路:
// 1. 将数组用set转换,使用while循环,终止条件是取到数组的长度。
// 2. 使用has()判断当前值是否在set数据结构中,不在则返回这个值,在则将当前值加1
function minNumberDisappeared( nums ) {
    
    
  // 会超时
  // if(!nums.length) return 1
  // let i = 1
  // while(i <= nums.length){
    
    
  //   if(!nums.includes(i)){
    
    
  //     return i
  //   }else{
    
    
  //     i++
  //   }
  // }
  // return i

  let set = new Set(nums);
  let i = 1;
  if(!nums.length) return 1
  while(i <= nums.length){
    
    
    if(!set.has(i)){
    
    
      return i
    }else{
    
    
      i++;
    }
  }
  return i;
}


5. Descripción de la suma de tres números : Dada una matriz S con n elementos, ¿hay algún elemento a, b, c en S que satisfaga a+b+c=0? Encuentre todos los triples en la matriz S que cumplan la condición.
Requisitos : Complejidad espacial: O (n2), Complejidad temporal O (n2)
Nota : Los elementos del triplete (a, b, c) deben estar en orden no descendente. (es decir, a≤b≤c) el conjunto de solución no puede contener tripletes repetidos.

Ejemplo 1
Entrada: [0]
Valor de retorno: []

Ejemplo 2
de entrada: [-2,0,1,1,2]
valor de retorno: [[-2,0,2],[-2,1,1]]

Ejemplo 3
de entrada: [-10,0,10,20,-10,-40]
valor de retorno: [[-10,-10,20],[-10,0,10]]

// 思路:
// 1. 如果数组长度小于3,直接返回空数组 []
// 1. 先将原数组按照从小到大的顺序排序
// 2. 定义一个新数组 array 用来存储满足条件的结果
// 3. 在排序后的数组中遍历,设定两个值,一个是 head = i+1,一个是tail = 数组长度 -1
// 4. 执行一个while循环,循环条件是head < tail
// 5. 对当前值,head 和 tail 指向的值做一个求和操作。对求和结果判断,如果结果为 0,则将这三个值放进一个数组中并push进 array 中同时则将 haed +1 向后移一位,tail - 1向前移动一位。
// 如果大于零则将 tail - 1,如果小于零则将 head + 1
// 6. 对循环结束后得到的 array 数组,进行二维数组的去重操作。
// 7. 二维数组去重
//  (1)将里面的每一项用 JSON.stringify 变为字符串
//  (2)将上述结果用 new Set() 去重,在将结果里面的每一项用 JSON.parse()反转回去

function threeSum( num ) {
    
    
  let len = num.length
  if(len < 3) return []
  let arr = []
  num.sort((a,b) => a -b)
  for(let i=0;i<len - 2;i++){
    
    
    let head = i + 1, tail = len - 1
    while(head < tail){
    
    
      let sum = num[i] + num[head] + num[tail]
      if(sum > 0){
    
    
        tail--
      }else if(sum < 0){
    
    
        head++
      }else{
    
    
        arr.push([num[i], num[head], num[tail]])
        head++
        tail--
      }
    }
  }
  // 对 array 数组,进行二维数组的去重操作
  let stringArr = arr.map(item => JSON.stringify(item))
  let setArr = [...new Set(stringArr)]
  let resultArr = setArr.map(ele => JSON.parse(ele))
  return resultArr
}
console.log(threeSum([-2,0,1,1,2]));

Cuatro Lista enlazada

1. Lista enlazada inversa
Descripción: Dado un único nodo principal de lista enlazada pHead (el nodo principal tiene un valor, por ejemplo, su valor es 1), la longitud es n, después de invertir la lista enlazada, devuelve una nueva lista enlazada.

Ejemplo 1
Entrada: {1,2,3}
Valor de retorno: {3,2,1}

Ejemplo 2
Entrada: {}
Valor de retorno: {}
Explicación: si la lista vinculada está vacía, la salida está vacía

// 思路:
// 1. 定义两个指针,一个 pre 指向 null,一个 cur 指向当前表头
// 2. 将cur.next存起来,因为是单链表,不保存的话,改变方向之后就找不到旧节点的下个节点了
// 3. 直接改变链表方向,将cur.next 指向 pre。
// 4. 将 pre 和 cur 逐渐向后面移动,直到 cur 指向 null,此时返回 pre
function ReverseList( head ) {
    
    
  // write code here
  let pre = null
  let cur = head
  while(cur){
    
    
    let temp = cur.next
    cur.next = pre
    pre = cur
    cur = temp
  }
  return pre
}

2. Reversión dentro del área especificada

Cinco Árbol binario

1. Recorrido frontal, medio y posterior del árbol binario

// 一. 前序遍历:根左右
// 描述:给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
// 输入:{1,#,2,3}
// 返回值:[1,2,3]

/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */
 
// 思路:
// 1. 先判断是否为空二叉树
// 2. 递归遍历左右子树
function preorderTraversal( root ) {
    
    
  let res = []
  function preorder(node){
    
    
    if(!node) return 
    res.push(node.val)
    preorder(node.left)
    preorder(node.right)
  }
  preorder(root)
  return res
}

// 二. 中序遍历:左根右
// 描述:给你二叉树的根节点 root ,返回它节点值的 中序 遍历。
// 输入:{1,2,#,#,3}
// 返回值:[2,3,1]
function inorderTraversal( root ) {
    
    
  let res = []
  function inorder(node){
    
    
    if(!node) return 
    inorder(node.left)
    res.push(node.val)
    inorder(node.right)
  }
  inorder(root)
  return res
}



// 三. 后序遍历:左右根
// 描述:给定一个二叉树,返回他的后序遍历的序列。
// 输入:{1,#,2,3}
// 返回值:[3,2,1]
function postorderTraversal( root ) {
    
    
  let res = []
  function postorder(node){
    
    
    if(!node) return 
    postorder(node.left)
    postorder(node.right)
    res.push(node.val)
  }
  postorder(root)
  return res
}


2. Descripción del recorrido de orden de nivel del árbol binario : Dado un árbol binario, devuelve el resultado del recorrido de orden de nivel del árbol binario (de izquierda a derecha, atravesando capa por capa) Requisitos
: 0 <= número de nodo del árbol binario <= 1500

Ejemplo 1 :
Entrada: {3,9,20,#,#,15,7}
Salida: [[3], [9, 20], [15, 7]]

Ejemplo 2
Entrada: {1,2}
Valor de retorno: [[1],[2]]

Ejemplo 3
entrada: {1,2,3,4,#,#,5}
valor de retorno: [[1],[2,3],[4,5]]

// 思路:
// 1. 如果是空二叉树返回一个空数组
// 2. 新建两个数组 res = [](用来存储最终的结果),queue = [root](用来存储每一层的结果)
// 3. 当 queue 这个数组的长度不为零时候,通过while循环将每一层的数据放入 queue 中。
// 4. 将 queue 这个数组放入 res 中。对左右子树依然执行步骤三
function levelOrder( root ) {
    
    
  if(!root) return []
  let res = [], queue = [root]
  while (queue.length) {
    
    
    res.push(queue.map(node => node.val));
    queue = queue.reduce((q, node) => {
    
    
      node.left && q.push(node.left);
      node.right && q.push(node.right);
      return q;
    }, []);
  }
  return res;
}


3. Imprima la descripción del árbol binario en orden de zigzag : dado un árbol binario, devuelva el recorrido en orden de capa de zigzag del árbol binario (la primera capa es de izquierda a derecha, la siguiente capa es de derecha a izquierda y siempre alterna así )

Ejemplo 1
Entrada: {1,2,3,#,#,4,5}
Valor de retorno: [[1],[3,2],[4,5]]
Explicación: Como se explica en el título, la primera capa son los nodos raíz, imprime los resultados de izquierda a derecha, de derecha a izquierda para la segunda capa y de izquierda a derecha para la tercera capa.

Ejemplo 2
de entrada: {8,6,10,5,7,9,11}
valor de retorno: [[8],[10,6],[5,7,9,11]]

Ejemplo 3
Entrada: {1,2,3,4,5}
Valor de retorno: [[1],[3,2],[4,5]]

// 思路:按照层序遍历的方式,将偶数项翻转排列,层序遍历的思路见上
function Print( pRoot ) {
    
    
  if(!pRoot) return []
  let res = [], queue = [pRoot], floor = 1;
  while(queue.length){
    
    
    // 判断是奇数层还是偶数层,如果是奇数层直接放入数组中,如果是偶数层先反转一下再放进数组中
    if(floor % 2 == 1){
    
    
      // 奇数层
      res.push(queue.map(node => node.val))
    }else{
    
    
      // 偶数层
      res.push(queue.map(node => node.val).reverse())
    }
    queue = queue.reduce((q, node) => {
    
    
      node.left && q.push(node.left);
      node.right && q.push(node.right);
      return q;
    }, [])
    floor++
  }
  return res
}

Supongo que te gusta

Origin blog.csdn.net/du_aitiantian/article/details/132151605
Recomendado
Clasificación