Press "Enter" to skip to content

Huahua's Tech Road

花花酱 LeetCode 2353. Design a Food Rating System

Hashtable + TreeSet / OrderedSet

用了三个Hashtable…

  1. 菜名 -> 菜系
  2. 菜系 -> Treemap
  3. 菜名 -> 所在Treemap中的迭代器

每个菜系用一个TreeSet来保存从高到低的菜色排名,查询的时候只要拿出第一个就好了。

修改的时候,拿出迭代器,删除原来的评分,再把新的评分加入(别忘了更新迭代器)

时间复杂度:构造O(nlogn),修改O(logn),查询O(1)

空间复杂度:O(n)

花花酱 LeetCode 3242. Design Neighbor Sum Service

青铜 Brute Force:每次需要花费O(n*n)的时间去查找query所在的格子,求和是O(1)。总的时间复杂度达到O(n^4),肯定会超时。

白银 Hashtable:由于所有元素的值的唯一的,我们可以使用hashtable(或者数组)来记录value所在的格子坐标,这样每次Query都是O(1)时间。
时间复杂度:初始化O(n^2),query O(1)。
空间复杂度:O(n^2)

黄金 Precompute:在初始化的时候顺便求合,开两个数组一个存上下左右的,一个存对角线的。query的时候直接返回答案就可以了。
时间复杂度和白银是一样的,但会快一些(省去了求合的过程)。

花花酱 LeetCode 3462. Maximum Sum With at Most K Elements

本题使用了两次 partial sorting / std::nth_element 来进行部分排序,可以作为经典教程了。

速度比全排序或者heap/pq快到不知道哪里去了~

Time complexity: O(m*n)
Space complexity: O(m*n)

不用黑科技就达到99.77%

花花酱 LeetCode 3408. Design Task Manager

  1. pq_ 使用std::map充当优先队列,存储(priority, taskId) -> userId
  2. m_ 使用std::unordered_map,存储taskId -> pq_的迭代器

所有操作都是O(logn)

花花酱 LeetCode 3489. Zero Array Transformation IV

一道不错的DP题目!

首先看到每次可以取任意一个nums[l] ~ nums[r]的子集

  • 不能用贪心(无法找到全局最优解)
  • 不能用搜索 (数据规模太大,(2^10) ^ 1000)

那只能用动态规划了

状态定义: dp[k][i][j] 能否通过使用前k个变换使得第i个数的值变成j

边界条件: dp[0][i][nums[i]] = 1,不使用任何变换,第i个数可以达到的数值就是nums[i]本身。

状态转移:dp[k][i][j] = dp[k-1][i][j] | (dp[k – 1][i][j + val[k]] if l[k] <= i <= r[k] else 0)

简单来说如果第k-1轮第i个数可以变成j + val[k],那么第k轮就可以通过减去val[k]变成j。

上面是拉的公式,我们也可以写成推的:

dp[k][i][j – val[k]] = dp[k-1][i][j – vak[k]] | (dp[k – 1][i][j] if l[k] <= i <= r[k] else 0)

当然这么定义的话空间复杂度太高O(10^7),由于第k轮的初始状态就等于k-1轮的状态,我们可以使用滚动数组来降维,空间复杂度降低到O(10^4)。

时间复杂度:O(k*n*MaxV) = O(10^7)。

剪枝优化

上面我们把整个数组看作一个整体,一轮一轮来做。但如果某些数在第k轮能到变成0了,就没有必要参与后面的变化了,或者说它用于无法变成0,那么就是无解,其他数也就不需要再计算了。

所以,我们可以对每个数单独进行dp。即对于第i个数,计算最少需要多少轮才能把它变成0。然后对所有的轮数取一个最大值。总的时间复杂度不变(最坏情况所有数都需要经过K轮)。空间复杂度则可以再降低一个纬度到O(MaxV) = O(10^3)。

再加速:我们可以使用C++ bitset的右移操作符,dp >> v,相当于把整个集合全部剪去v,再和原先的状态做或运算(集合并)来达到新的状态。时间复杂度应该是一样的,只是代码简单,速度也会快不少。注: dp>>v 会创建一个临时对象,大小为O(MaxV)。

举个例子:
dp = {2, 3, 7}
dp >> 2 -> {0, 1, 5}
dp |= dp >> v -> {0, 1, 2, 3, 5, 7]