Leetcode_328周赛

你好旅行者!欢迎来到cyt的练功房。本篇文章来记录一下力扣的第328场周赛

一、数组元素和与数字和的绝对差

题目:

给你一个正整数数组 nums

  • 元素和nums 中的所有元素相加求和。
  • 数字和 是 nums 中每一个元素的每一数位(重复数位需多次求和)相加求和。
    返回 元素和数字和 的绝对差。

注意:两个整数 xy 的绝对差定义为 |x - y|

输入:nums = [1,15,6,3]

输出:9

解法:

很简单的一道题,就是总的和加上每个数字的和。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
int differenceOfSum(vector<int>& nums) {
int nums1=0,nums2=0;
for(int i=0;i<nums.size();i++){
nums1+=nums[i];
while(nums[i]){
nums2+=nums[i]%10;
nums[i]/=10;
}
}
return abs(nums1-nums2);
}
};

二、子矩阵元素加 1

题目:

给你一个正整数 n ,表示最初有一个 n x n 、下标从 0 开始的整数矩阵 mat ,矩阵中填满了 0

另给你一个二维整数数组 query 。针对每个查询 query[i] = [row1i, col1i, row2i, col2i] ,请你执行下述操作:

找出 左上角 为(row1i, col1i) 且 右下角 为 (row2i, col2i) 的子矩阵,将子矩阵中的 每个元素 加 1 。也就是给所有满足 row1i <= x <= row2i 和 col1i <= y <= col2i 的 **mat[x][y]**加 1 。
返回执行完所有操作后得到的矩阵 mat 。

download

解法:

二维差分模板题,建议直接使用模板进行差分的构建,构建完之后求个前缀和就行了,唯一要注意的是在构建差分数组时数组要多开一个,wa了一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
vector<vector<int>> rangeAddQueries(int n, vector<vector<int>> &queries) {
vector<vector<int>> mat(n, vector<int>(n, 0));
vector<vector<int>> diff(n+1, vector<int>(n+1, 0));
for (int k = 0; k < queries.size(); k++) {
int x1 = queries[k][0];
int y1 = queries[k][1];
int x2 = queries[k][2];
int y2 = queries[k][3];
diff[x1][y1]++;
diff[x2+1][y1]--;
diff[x2+1][y2+1]++;
diff[x1][y2+1]--;
}
for(int i = 0; i < n; ++i){
for(int j = 0; j < n; ++j){
if(i > 0) diff[i][j] += diff[i - 1][j];
if(j > 0) diff[i][j] += diff[i][j - 1];
if(i > 0 && j > 0) diff[i][j] -= diff[i - 1][j - 1];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
mat[i][j]=diff[i][j];
}
}
return mat;
}
};

三、统计好子数组的数目

题目:

给你一个整数数组 nums 和一个整数 k ,请你返回 nums 中 好 子数组的数目。

一个子数组 arr 如果有 至少 k 对下标 (i, j) 满足 i < j 且 arr[i] == arr[j] ,那么称它是一个 好 子数组。

子数组 是原数组中一段连续 非空 的元素序列。

解法:

子数组是一个连续的过程,思考大致为双指针算法仔细一思考确实是当j确定时,i单调向前进,所以可以用双指针来做。

定义[i,j]用hash表存储[i,j]中每个数出现的次数,res为出现的对数,hash[c]每多出现一次,res就增加hash[c]-1;
首先移动j,当j移动到某一个res>=k时ans++,(此时不能是ans+=(nums.size()-j),因为j会继续移动导致重复计算),在res>=k时,移动i,i每次向右移动一个判定是否成立,若成立,则ans+=(nums.size()-j),这个不会重复。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public:
long long countGood(vector<int>& nums, int k) {
long long i=0,j=1,res=0,ans=0;
unordered_map<int,long long> hash;
hash[nums[0]]++;
while(j<nums.size()){
hash[nums[j]]++;
if(hash[nums[j]]>1)res+=(hash[nums[j]]-1);
if(res>=k){
ans+=1;
}
while(i<j){
res-=(hash[nums[i]]-1);
if(res>=k){
ans+=(nums.size()-j);
hash[nums[i++]]--;
}
else{
res+=(hash[nums[i]]-1);
break;
}
}
j++;
}
return ans;

}
};

四、最大价值和与最小价值和的差值

根本做不出来,感觉应该是树形dp,写出来超时,看了题解也不知道为啥错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
long ans=0;
// dp的含义是从x到fa的最大路径和第二大路径
pair<long,long> dp(int x,int fa,vector<vector<int>> tu,vector<int> price){
long max_s1=price[x],temp=price[x];
long max_s2=0;
pair<long,long> p;
for(auto y:tu[x]){
if(y==fa)continue;
auto[s1, s2] = dp(y, x,tu,price);
ans=max(ans, max(max_s1 + s2, max_s2 + s1));
max_s1=max(max_s1,s1+temp);
max_s2=max(max_s2,s2+temp);
}
return {max_s1,max_s2};
}
long long maxOutput(int n, vector<vector<int>>& edges, vector<int>& price) {
vector<vector<int>> tu(n);
for(auto x:edges){
tu[x[0]].push_back(x[1]);
tu[x[1]].push_back(x[0]);
}
dp(0,0,tu,price);
return ans;
}
};
使用搜索:谷歌必应百度