leetcode update

This commit is contained in:
gameloader 2025-02-15 14:27:04 +08:00
parent 36ebe60b0c
commit 763fc4b56f

View File

@ -23022,3 +23022,129 @@ public:
```
### 总结
注意到想构建优先级队列需要定义好三个属性,一是优先级队列中保存的数据类型,二是用来保存这些数据的容器类型,三则是优先级队列中的比较函数,定义好这三个抽象出来的属性就可以定义好一个优先级队列。
## day341 2025-02-14
### 1352. Product of the Last K Numbers
Design an algorithm that accepts a stream of integers and retrieves the product of the last k integers of the stream.
Implement the ProductOfNumbers class:
ProductOfNumbers() Initializes the object with an empty stream.
void add(int num) Appends the integer num to the stream.
int getProduct(int k) Returns the product of the last k numbers in the current list. You can assume that always the current list has at least k numbers.
The test cases are generated so that, at any time, the product of any contiguous sequence of numbers will fit into a single 32-bit integer without overflowing.
![0214ihsIIEExavkj](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0214ihsIIEExavkj.png)
### 题解
本题注意要求添加和获取尾部乘积的时间复杂度都为O(1)添加数字比较简单直接向数组尾部添加数字就能满足时间复杂度计算乘积相对来说复杂一些因为添加数字是从前向后添加此处考虑如果是获取尾部的k个数字的和首先想到的就是使用前缀和用n对应的前缀和和n-k对应的前缀和做差即得尾部的k个数字的和前缀和的好处在于从前向后添加数字的过程中可以一边添加数字一边计算出来且计算出来后不会发生变化后续不需要额外的计算但后缀和在向尾部添加数字的时前面数字的后缀和一直在改变。
本题也可以采用类似的思路只是使用的不是前缀和而是前缀积要获取尾部k个数字的积只需将n对应的前缀积和n-k对应的前缀积做除法。但乘积有一个特殊的因素即出现0的情况在出现0后对应的前缀积直接变为0假设0出现在位置m处则全部包含m位置的积都为0此处常规状态下做除的方式不再适用因此对于前缀积当出现0时就将整个前缀积数组清空后续计算尾部k个数字的积时如果k大于当前前缀积数组的长度说明这k个数字中一定包含一个0直接返回0即可初始状态除外即还没有遇到过0但数组长度小于k的情况。其余情况下使用前缀积做除可得尾部k个数字的积且满足时间复杂度为O(1)
此处在每次重置前缀积数组时先放置一个哨兵数字1就可以使用同一种处理方式直接处理数组长度大于等于k的情况等于k时不用再额外处理可以通用做除的方式
### 代码
```cpp
class ProductOfNumbers {
public:
vector<int> nums;
vector<int> products;
ProductOfNumbers() {
products.push_back(1);
}
void add(int num) {
nums.push_back(num);
if(num == 0){
products.clear();
products.push_back(1);
}else{
products.push_back(products[products.size()-1]*num);
}
}
int getProduct(int k) {
if(products.size() <= k){
return 0;
}else{
return products[products.size()-1]/products[products.size()-1-k];
}
}
};
/**
* Your ProductOfNumbers object will be instantiated and called as such:
* ProductOfNumbers* obj = new ProductOfNumbers();
* obj->add(num);
* int param_2 = obj->getProduct(k);
*/
```
## day342 2025-02-15
### 2698. Find the Punishment Number of an Integer
Given a positive integer n, return the punishment number of n.
The punishment number of n is defined as the sum of the squares of all integers i such that:
1 <= i <= n
The decimal representation of i * i can be partitioned into contiguous substrings such that the sum of the integer values of these substrings equals i.
![0215x0cnJw0JOA4K](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0215x0cnJw0JOA4K.png)
### 题解
本题注意题目条件n的范围仅有1000而惩罚数计算方式中整数i的条件的第二条i的平方可以被分割成两个子字符串且子字符串代表的整数的和与i相等这一条件只和i本身有关也就是说i是否满足该条件可以提前算出因此可以直接遍历1~1000依次计算i是否满足该条件若满足则将i的平方加入到前缀和中用数组保存到下标i的满足条件的所有数字的平方的前缀和。对于n直接使用查表法查到n对应的平方前缀和即为最终结果。
要解决的关键问题即为如何判断i是否满足第二个条件类似的问题之前也曾多次遇到对于该问题只能遍历出字符串的所有可能的分割组合并判断只是在遍历过程中可以通过条件进行剪枝。遍历字符串分割组合可以使用回溯法即先分割前面一个字符再递归处理后面的字符串再分割前面两个字符...以此类推。在处理过程中可以传入i减去之前分割出来的数字后的差即剩余的还需要填补的数量如果差为负数说明前面的数字已经过大可以直接从该分支中返回继续下一个分支的分割。
此时可以想到将数字和字符串来回转化要花费大量的时间是否可以避免这种转换开销呢对于字符串我们每次可以从前向后先分割出一个字符再分割出两个字符而对于数字其实也可以做类似的操作只是会从右向左如果将数字模10就可以分割出一个最右侧数字将数字模100就可以分割出两个最右侧数字由于本题中我们找计算的是分割的组合因此分割的方向不重要这种分割方法得到的结果是相同的但避免了转换开销。
### 代码
```cpp
class Solution {
public:
int punishmentNumber(int n) {
std::vector<int> prefix_sums(1001, 0);
for (int i = 1; i <= 1000; ++i) {
prefix_sums[i] = prefix_sums[i - 1];
if (is_punishment_number(i)) {
prefix_sums[i] += i * i;
}
}
return prefix_sums[n];
}
private:
bool is_punishment_number(int i) {
return can_partition(i * i, i);
}
bool can_partition(int num, int remaining_target) {
if (num == 0) {
return remaining_target == 0;
}
int divisor = 1;
while (num / divisor > 0) {
int current_num = num % (divisor*10);
if (current_num > remaining_target) {
break;
}
if (can_partition(num / (divisor * 10), remaining_target - current_num))
{
return true;
}
if (divisor > num / 10) break;
divisor *= 10;
}
if(num == remaining_target){
return true;
}
return false;
}
};
```