记忆Java递归函数

时间:2020-02-20 10:03:48

标签: javascript recursion memoization

我具有此递归函数,该函数接收一副套牌,并找到特定牌的索引:

const getCardIndex = (deck, fullCardName) => fullCardName === deck[0] ? 52 - deck.length : getCardIndex(deck.splice(1), fullCardName)

const deck = 'Ace of Hearts, Ace of Diamonds, Ace of Clubs, Ace of Spades, Two of Hearts, Two of Diamonds, Two of Clubs, Two of Spades, Three of Hearts, Three of Diamonds, Three of Clubs, Three of Spades, Four of Hearts, Four of Diamonds, Four of Clubs, Four of Spades, Five of Hearts, Five of Diamonds, Five of Clubs, Five of Spades, Six of Hearts, Six of Diamonds, Six of Clubs, Six of Spades, Seven of Hearts, Seven of Diamonds, Seven of Clubs, Seven of Spades, Eight of Hearts, Eight of Diamonds, Eight of Clubs, Eight of Spades, Nine of Hearts, Nine of Diamonds, Nine of Clubs, Nine of Spades, Ten of Hearts, Ten of Diamonds, Ten of Clubs, Ten of Spades, Jack of Hearts, Jack of Diamonds, Jack of Clubs, Jack of Spades, Queen of Hearts, Queen of Diamonds, Queen of Clubs, Queen of Spades, King of Hearts, King of Diamonds, King of Clubs, King of Spades'.split(', ')

const result = getCardIndex(deck, 'King of Spades')

console.log(result)

有什么办法可以加快它的速度,即使用记忆吗?

2 个答案:

答案 0 :(得分:1)

正如评论所建议的那样,没有理由递归地执行此操作。 indexOf很好地解决了这个问题。

但是,如果您决心编写一个递归解决方案,那么您的技术就会遇到很大的问题。您正在破坏要搜索的对象!

Array.prototype.splice是破坏性的。它改变了它工作的数组。最后,您将获得一个索引和几乎空的一副纸牌!

这完全是巧合。如果也许您打算使用slice,那将起作用并且不会出现此问题。 slice只是给您一个数组的副本,它从一个索引开始,到另一个索引(或数组的末尾)结束。splice做得更多。它删除元素的子列表,插入其他元素,然后返回删除的元素。如果您碰巧只用一个起始索引来调用它,它将删除数组的其余部分并返回它。因此,调用 deck.slice(1)deck.splice(1)恰好返回相同的内容,但是第二个也从数组中删除了所有返回的项目。

因此,对函数的最快修复就是这样:

const getCardIndex = (deck, fullCardName) => 
  fullCardName === deck[0] 
    ? 52 - deck.length 
    : getCardIndex (deck.slice(1), fullCardName)

但是,说实话,这没有什么意义。它可以工作,但是在每次递归调用时,它都会构建一个新数组,比以前的版本短一个。一个简单的搜索就需要很多内存。

所以这是另一种仅在索引上递归的技术:

const getCardIndex = (deck, fullCardName, idx = 0) =>
  idx >= deck.length 
    ? -1
    : deck [idx] == fullCardName
      ? idx
      : getCardIndex (deck, fullCardName, idx + 1)

但是,请注意,除了变量和函数的名称外,对于纸牌和卡片没有任何其他意义。因此,我们可以将其转换为更通用的函数,如下所示:

const getIndex = (xs, x, idx = 0) =>
  idx >= xs.length 
    ? -1
    : xs [idx] == x
      ? idx
      : getIndex (xs, x, idx + 1)

我们有一个递归解决方案,用于在任意数组中查找值的索引。

不过,再次使用此功能的理由很少。这是学习递归的合理练习,但除此之外就不多了。请改用indexOf

答案 1 :(得分:-1)

对于可以先识别解决方案(O(52) = O(1))的解决方案,然后可以在一次操作中查找解决方案,放弃递归函数,将平台变成一个对象,其键是卡名称,值是卡索引,然后只需在对象上查找卡属性:

const deck = 'Ace of Hearts, Ace of Diamonds, Ace of Clubs, Ace of Spades, Two of Hearts, Two of Diamonds, Two of Clubs, Two of Spades, Three of Hearts, Three of Diamonds, Three of Clubs, Three of Spades, Four of Hearts, Four of Diamonds, Four of Clubs, Four of Spades, Five of Hearts, Five of Diamonds, Five of Clubs, Five of Spades, Six of Hearts, Six of Diamonds, Six of Clubs, Six of Spades, Seven of Hearts, Seven of Diamonds, Seven of Clubs, Seven of Spades, Eight of Hearts, Eight of Diamonds, Eight of Clubs, Eight of Spades, Nine of Hearts, Nine of Diamonds, Nine of Clubs, Nine of Spades, Ten of Hearts, Ten of Diamonds, Ten of Clubs, Ten of Spades, Jack of Hearts, Jack of Diamonds, Jack of Clubs, Jack of Spades, Queen of Hearts, Queen of Diamonds, Queen of Clubs, Queen of Spades, King of Hearts, King of Diamonds, King of Clubs, King of Spades'.split(', ')
const deckObj = Object.fromEntries(deck.map((str, i) => [str, i]));


console.log(deckObj['King of Spades'])
console.log(deckObj['Ace of Diamonds'])
console.log(deckObj['Queen of Diamonds'])

相关问题