1
/** https://leetcode.com/problems/shopping-offers/2
* @param {number[]} price3
* @param {number[][]} special4
* @param {number[]} needs7
var shoppingOffers = function (price, special, needs) {11
return shop(price, special, needs);14
var shop = function (price, special, needs) {15
// Return memoization result16
if (this.map.has(needs) === true) {17
return this.map.get(needs);20
// Calculate total if purchase without special offers21
let currTotal = calcTotal(price, needs);23
// Try every single offers24
for (let i = 0; i < special.length; i++) {25
// Check special offer can be used26
if (canUseSpecial(special[i], needs) === true) {27
// Clone the `needs` because we don't want to modify the original `needs`, update the `needs` count by calling `useSpecial()`28
let cloneNeeds = [...needs];29
cloneNeeds = useSpecial(special[i], cloneNeeds);31
// Count total if using special offers, basically repeat the same process with updated `needs`32
let totalUsingSpecial =33
special[i][needs.length] + shop(price, special, cloneNeeds);35
// Compare the `currTotal` with total if using special offers36
currTotal = Math.min(currTotal, totalUsingSpecial);40
// Update memoization and return result41
this.map.set(needs, currTotal);45
var calcTotal = function (price, needs) {46
// Calculate total if purchase without special offers, basically `price[i] * needs[i]`49
for (let i = 0; i < price.length; i++) {50
out += price[i] * needs[i];56
var canUseSpecial = function (special, needs) {57
// Check if special offers can be used, if any of `special[i]` is more than `needs[i]`, the special can not be used, return false because we can not buy more than needed58
for (let i = 0; i < needs.length; i++) {59
if (needs[i] < special[i]) {67
var useSpecial = function (special, needs) {68
// Update the `needs` count by subtracting it from `special`69
for (let i = 0; i < needs.length; i++) {70
needs[i] -= special[i];