【发布时间】:2020-11-01 11:56:02
【问题描述】:
我在 LeetCode 上解决了最长递增子序列问题:https://leetcode.com/problems/longest-increasing-subsequence/
给定一个未排序的整数数组,求最长递增子序列的长度。对于
[10,9,2,5,3,7,101,18],答案是4([2,3,7,101]的大小)。
class Solution {
public:
int helper(vector<int>& nums, unordered_map<int, vector<int>>& dp, int lastNum, int startIndex) {
if(startIndex>=nums.size()) return 0;
if(dp.find(lastNum)!=dp.end() && dp[lastNum].size()>=startIndex && dp[lastNum][startIndex]!=INT_MIN) {
return dp[lastNum][startIndex];
}
int ans=0;
if(nums[startIndex]>lastNum) ans=1+helper(nums, dp, nums[startIndex], startIndex+1);
ans=max(ans, helper(nums, dp, lastNum, startIndex+1));
return dp[lastNum][startIndex]=ans;
}
int lengthOfLIS(vector<int>& nums) {
int ans=0;
unordered_map<int, vector<int>> dp;
dp[INT_MIN].resize(10001, INT_MIN);
for(int i=0; i<nums.size(); i++) dp[nums[i]].resize(10001, INT_MIN);
return helper(nums, dp, INT_MIN, 0);
}
};
请注意,我也在记忆它,使用上面的 dp 表并使用两个状态 lastNum(我们在上次递归中选择的 nums[i] 值)和 startIndex。在solution section 中,它们使用两个状态prev(index,不像我使用lastNum 传递的值)和curpos(类似于startIndex )。
我很困惑,因为我仍然得到 TLE。现在我知道在线评委设置的时间限制是任意的,但我想看看为什么使用lastNum 而不是prev 作为状态会导致更多的执行时间。同样,我还能做其他优化吗?
谢谢!
编辑:我把它改成了10001,根据Igor在cmets中的建议,现在所有的测试用例都通过了,但是需要很多时间:
24 / 24 个测试用例通过,但耗时过长。
Edit2:换一种说法,我想我的问题是,作为面试官,人们会提供什么建议来推动候选人朝着正确的方向前进(使用prev 而不是lastNum)?
【问题讨论】:
-
10000001 的平方约为 100GB。如果成功的话,仅仅分配这么多 RAM 就需要很长时间。
-
哦,你为什么要平方呢?
-
因为你在一个循环中分配了 10000001 个元素的向量,这可能会运行多达 10000001 次迭代。
-
将其更改为
10001,我仍然得到24 / 24 test cases passed, but took too long. -
好的,我现在明白了。你能建议一些其他的方法来记忆它吗?也许使用
unordered_map<int, vector<int>>以外的东西?
标签: c++ algorithm optimization dynamic-programming