小红书7.23笔试
本人是道听途说选手(base不合没投xhs),在牛客上看完题目顺便打一下题目,交流交流
第二题 精华帖子数量
O(n)听说会超时,我的想法是每个区间左端点找到匹配的右端点,二分查找,时间复杂度为O(mlogm),m为1e5,n为1e9,O(mlogm)远低于O(n)
更新:前缀和+滑动窗口可以达到O(m),代码已更新,写了大概思想,可能没太仔细推敲细节
int main(){ int n, m, k; cin>>n>>m>>k; vector<vector<int>>interval; for(int i = 0; i < m; i++){ int l, r; cin>>l>>r; interval.push_back(vector<int>{l, r}); } // 前缀和 vector<int> pre(interval.size()+1, 0); for(int i = 1; i <= interval.size(); i++){ pre[i] = pre[i-1] + (interval[i-1][1] - interval[i-1][0]); } int maxNum = 0; int r = 0; for(int i = 0; i < m; i++){ while(r < m){ if(interval[r][0] - interval[i][0] <= k){ r++; } else break; } int count = pre[r-1] - pre[i]; // cout<<r<<' '<<i<<' '<<count<<endl; int z = min(interval[r-1][1], interval[i][0] + k) - interval[r-1][0]; count += z; maxNum = max(count, maxNum); } cout<<maxNum<<endl; }
第三题 最大连续子数组和
dp[i][0]表示不进行替换的最大和
dp[i][1]表示进行替换后的最大和
int Solution(vector<int>&nums, int x){ vector<vector<int>> dp(nums.size(),vector<int>(2,1)); dp[0][0] = nums[0]; dp[0][1] = x; for(int i=1;i<nums.size();i++){ // 不替换 = 上一个不替换 或 当前 nums[i] dp[i][0] = max(dp[i-1][0]+nums[i],nums[i]); // 替换 = 上一个不替换+x 或 x 或 上一个替换+nums[i] dp[i][1] = max(max(dp[i-1][0]+x,x),dp[i-1][1]+nums[i]); } int maxSum = INT_MIN; for(int i=0;i<nums.size();i++){ if(dp[i][0]>maxSum) maxSum = dp[i][0]; if(dp[i][1]>maxSum) maxSum = dp[i][1]; } return maxSum; }