简体   繁体   English

递归记忆 function

[英]memoization of recursive function

I am solving this problem and I solved it recursively.我正在解决这个问题,我递归地解决了它。 For the larger test case, it was giving me error of time out so I tried to create memoization.对于较大的测试用例,它给我超时错误,所以我尝试创建记忆。

https://leetcode.com/problems/frequency-of-the-most-frequent-element/description/ https://leetcode.com/problems/frequency-of-the-most-frequent-element/description/

The frequency of an element is the number of times it occurs in an array.元素的频率是它在数组中出现的次数。

You are given an integer array of nums and an integer k.给定一个 integer 数组和一个 integer k。 In one operation, you can choose an index of nums and increment the element at that index by 1.在一个操作中,您可以选择 nums 的索引并将该索引处的元素递增 1。

Return the maximum possible frequency of an element after performing at most k operations.在执行最多 k 个操作后返回元素的最大可能频率。

Example 1:示例 1:

Input: nums = [1,2,4], k = 5 Output: 3 Explanation: Increment the first element three times and the second element two times to make nums = [4,4,4].输入:nums = [1,2,4], k = 5 Output: 3 解释:将第一个元素递增 3 次,将第二个元素递增 2 次,使 nums = [4,4,4]。 4 has a frequency of 3. 4 的频率为 3。

But the problem is that parameter of the function is an array like [1, 2, 4, 6] and k which is an integer value.但问题是 function 的参数是一个像 [1, 2, 4, 6] 这样的数组,而 k 是一个 integer 值。

I want memoization where I can check for a key which basically checks if the array and k value are already solved or not.我想要记忆,我可以在其中检查一个键,该键基本上检查数组和 k 值是否已经解决。

My problem here in the code is that我在代码中的问题是

suppose for a function there is an array [1, 4, 5] and k =3, I check for a key of "1-4-5-3" and if it is not present I do a recursion call whereas if there was the solution for [1, 5, 4] and k=3, or [5, 1, 4] for k = 3 it should have also said that it is already solved.假设对于 function 有一个数组 [1, 4, 5] 并且 k = 3,我检查一个键“1-4-5-3”,如果它不存在我做一个递归调用,而如果有[1, 5, 4] 和 k=3 的解决方案,或 [5, 1, 4] 对于 k = 3 的解决方案它也应该说它已经解决了。

var maxFrequency = function(nums, k, memo = {}) {
    if(k==0){
        return countFrequency(nums);
    }
    let key = ""
    nums.forEach((element, index)=>{
        key = key + "-" + element
    })
    key = key + "-" +  k
    if(nums[key]){
        return nums[key]
    }
    let result = []
    for(let i=0, _length = nums.length; i<_length; i++){
        let tempArray = [...nums]
        tempArray[i] += 1
        result[i] = maxFrequency(tempArray, k-1)
    }

    nums[key] = Math.max(...result)
    return nums[key]
};

function countFrequency(arr){
    let map = {}
    let maxFreq = 1
    for(let i=0, _length = arr.length; i<_length; i++){
        if(map.hasOwnProperty(arr[i])){
            map[arr[i]] += 1
            if(map[arr[i]]>maxFreq){
                maxFreq = map[arr[i]]
            }
        }
        else{
            map[arr[i]] = 1
        }
    }
    return maxFreq
}

It works for smaller data like它适用于较小的数据,例如

nums = [1,4,8,13] k = 5 got Output 2 for Expected 2 nums = [1,4,8,13] k = 5 得到 Output 2 对于预期 2

How can I apply memoization to this kind of problem?我怎样才能对这类问题应用记忆?

Thank you谢谢

Memoization is not going to help reduce the time complexity of your solution.记忆化不会帮助降低解决方案的时间复杂度。 Your algorithm is as brute force as can be, where every possible combination of increment-steps is attempted.您的算法尽可能地蛮力,其中尝试了增量步骤的所有可能组合。 With memoization you would eliminate cases where you come to the same result by applying the same increments but in a different order, but:通过记忆,您可以消除通过应用相同的增量但以不同的顺序获得相同结果的情况,但是:

  1. Those "duplicate" cases could be easily avoided by only producing increments from left-to-right and never to an element the precedes an element that was already incremented.那些“重复”的情况可以很容易地避免,只产生从左到右的增量,而不是在已经递增的元素之前的元素。 This approach makes the memoization unnecessary.这种方法使记忆变得不必要。
  2. That still represents a very inefficient algorithm这仍然是一个非常低效的算法

The right way to approach this problem is:解决这个问题的正确方法是:

  • Sort the elements in non-decreasing order对元素进行非降序排序

  • Apply a sliding window algorithm starting with a small window at the left side of the array (a window with 1 element):应用从数组左侧的小 window 开始的滑动 window 算法(具有 1 个元素的 window):

    • Extend the window at the right when the window can be flattened to one value with k increments当 window 可以以 k 为增量展平为一个值时,扩展右边的 window

    • Reduce the window at the left when the window cannot be flattened to one value with k increments当 window 不能以 k 为增量展平为一个值时,减少左边的 window

      Note that knowing how many increments are necessary to flatten a window can be deduced with a mathematical (incremental) formula -- you don't really have to perform those increments.请注意,可以使用数学(增量)公式推导出了解展平 window 需要多少增量——您实际上不必执行这些增量。

    • Keep track of what the largest window was that could be flattened to one value.跟踪可以展平为一个值的最大 window 是什么。

    • Repeat until the window reaches the right end of the array重复直到 window 到达数组的右端

  • Return the number of values in the largest valid window that was found.返回找到的最大有效 window 中值的个数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM