Algoritmo de cambio de moneda-01

1. Di algo

Siempre hay algoritmos, algoritmos, algoritmos Lin Lin siempre decía que hay doscientos pequeños, y he leído algunos artículos y libros.
Al ver cambiar la moneda, todavía no podía hacer nada.
Tienes que cambiar tu forma de pensar y tu estado de aprendizaje.

  1. Para cada pregunta, se deben escribir varias soluciones y complejidad de tiempo y espacio.
  2. Asegúrese de escribir un resumen, ¡esto es muy importante!

2. Descripción del título

Este problema es más común en nuestra vida diaria. Supongamos que tenemos billetes de 1 yuanes, 2 yuanes, 5 yuanes, 10 yuanes, 20 yuanes, 50 yuanes y 100 yuanes. Los números de ellos son c1, c2, c5, c10, c20, c50 y c100, respectivamente. Ahora vamos a utilizar este dinero para pagar yuanes K. ¿Cuál es la cantidad mínima de billetes que debemos utilizar?

3. Resumen

3.1 Ideas para la resolución de problemas

  1. Codicioso: busque el que tenga el valor nominal más grande y luego baje cuando no sea suficiente. La solución local no es la solución óptima, por lo que es la respuesta real enumerar todos los valores (es decir, el método de retroceso, agotar todas las respuestas)
  2. Programación dinámica: ¿Cuál es la cantidad máxima de un billete y la cantidad máxima de dos billetes es menor que la cantidad, recursividad? .

3.2 Resumen

  1. Codicioso no funciona.
  2. Se puede dar marcha atrás.
  3. La programación dinámica tiene dos soluciones, una matriz unidimensional y una matriz bidimensional, y la matriz unidimensional tiene dos soluciones.
  4. La recursividad tiene dos soluciones: recursividad y memorias recursivas.
  5. El retroceso y la recursividad es una solución, pero una es pensamiento y la otra es realización.
  6. Hay seis soluciones y siete realizaciones.
  7. La séptima realización, la mejor.

4. Solución

4.0 Algoritmo codicioso

Tiempo: Nivel exponencial.
Espacio: O (n) (n-ésimo espacio recursivo)

let coinChange = function (coins, amount, idxCoin = 0) {
    coins = coins.sort((a, b) => b - a) // 排序

    return _c(coins, amount, idxCoin)
}

let _c = function (arr, amount, count = 0) {
    if (amount < 0) {
        return -1;
    }

    if (amount === 0) {
        return count;
    }

    for (var i = 0; i < arr.length; i++) {
        let max = Math.floor(amount / arr[i]);

        for (var j = max; j > 0; j--) {
            let res = _c(arr, amount - j * arr[i], j + count)
            if (res !== -1) {
                return res
            }
        }
    }

    return -1;
}

4.1 Retroceso (agotamiento violento) (podado 4.2 recursividad)

Tiempo: Nivel exponencial.
Espacio: O (n) (n-ésimo espacio recursivo)

let coinChange = function (coins, amount,idxCoin=0) {
    return _c(coins, amount, idxCoin)
}

let _c = function(coins, amount, idxCoin){
        if (amount === 0) {
        return 0;
    }

    if (idxCoin < coins.length && amount > 0) {
        let maxVal = Math.round(amount / coins[idxCoin]);
        let minCost = Number.MAX_SAFE_INTEGER;
        for (let x = 0; x <= maxVal; x++) {
            if (amount >= x * coins[idxCoin]) {
                let res = _c(coins, amount - x * coins[idxCoin],idxCoin + 1);
                if (res !== -1) {
                    minCost = Math.min(minCost, res + x)
                }
            }
        }

        return (minCost === Number.MAX_SAFE_INTEGER) ? -1 : minCost
    }

    return -1;
}

4.2 Recursividad (forma de árbol de programación dinámica)

Complejidad temporal: Nivel exponencial (no solo relacionado con s, sino también relacionado con los exponentes de s-1 y s-2)
Complejidad espacial: O (s) (memoria espacial recursiva)

let coinChange = (coins, amount) => {
    if (amount < 1) {
        return 0;
    }

    return _coin(coins, amount)
}

let _coin = (coins, amount) => {
    console.log(amount)
    if (amount < 0) {
        return -1;
    }

    if (amount === 0) {
        return 0
    }

    let min = Number.MAX_SAFE_INTEGER;
    for (let coin of coins) {
        let res = _coin(coins, amount - coin);
        if (res >= 0 && res < min) {
            min = res + 1;
        }
    }

    return min === Number.MAX_SAFE_INTEGER ? -1 : min;
}

4.3 Recursion + Memoir (optimización recursiva)

Complejidad temporal: O (sn)
Complejidad espacial: O (S)

let coinChange = (coins, amount) => {
    if (amount < 1) {
        return 0
    }

    return _coin(coins, amount, new Array(amount).fill(0))
}

let _coin = (coins, amount, count) => {
    if (amount < 0) {
        return -1;
    }

    if (amount === 0) {
        return 0;
    }

    if (count[amount - 1] !== 0) {
        return count[amount - 1]
    }

    let min = Number.MAX_SAFE_INTEGER;
    for (let coin of coins) {
        let res = _coin(coins, amount - coin, count);
        if (res >= 0 && res < min) {
            min = res + 1;
        }
    }

    count[amount - 1] = (min === Number.MAX_SAFE_INTEGER) ? -1 : min;
    return count[amount - 1]
}

4.4 Programación dinámica + matriz bidimensional

Este es el algoritmo de programación dinámica más básico.
Complejidad temporal O (s s n)
Complejidad espacial: O (sn)

var coinChange = function(coins, amount) {
  if(amount === 0){
    return 0;
  }

  let n = amount+1;
  let dp = new Array(amount+1).fill(new Array(amount+1).fill(0));

  for(let i = 0; i < coins.length; i++){
    dp[0][coins[i]] = 1;
  }

  if(dp[0][n-1]){
    return 1;
  }

  for(let i = 1; i < n; i++){
    for(let j = n-1; j>=1; j--){
      dp[i][j] = dp[i-1][j];

      for(let m = 0; m < coins.length; m++){
        if(j + coins[m] <= amount && dp[i][j]){
          dp[i][j+coins[m]] = 1; 
        }
      }
    }

    if(dp[i][n-1]){
      return i+1;
    }
  }

  return -1;
};

4.5 Programación dinámica + matriz unidimensional

Complejidad temporal: O (sn)
Complejidad espacial: O (s)

思路 : dp [i] = min (dp [ix], dp [iy]) + 1;

var coinChange = function (coins, amount) {
    let dp = new Array(amount + 1).fill(Infinity);
    dp[0] = 0;

    for (let i = 1; i <= amount; i++) {
        for (let coin of coins) {
            if (i - coin >= 0) {
                dp[i] = Math.min(dp[i], dp[i - coin] + 1);
            }
        }
    }

    return dp[amount] === Infinity ? -1 : dp[amount];
}

4.6 Programación dinámica + matriz unidimensional (optimización)

Complejidad temporal: O (sn)
Complejidad espacial: O (s)

const coinChange = (coins, amount) => {
    let dp = new Array(amount + 1).fill(Number.MAX_SAFE_INTEGER);
    dp[0] = 0;
    for (let coin of coins) {
        for (let i = coin; i <= amount; i++) {
            dp[i] = Math.min(dp[i], dp[i - coin] + 1)
        }
    }
    return dp[amount] === Number.MAX_SAFE_INTEGER ? -1 : dp[amount]
}

Supongo que te gusta

Origin blog.csdn.net/a519991963/article/details/112271485
Recomendado
Clasificación