Leetcode-第10场双周赛

5079.三个有序数组的交集

解法1:map

思路:

因为是严格递增不存在一个数组中存在两个相同的数

用map存每个数字出现的次数,若该数字次数达到3次添加到结果数组中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
vector<int> arraysIntersection(vector<int>& arr1, vector<int>& arr2, vector<int>& arr3) {
map<int,int> m;
int n=arr1.size();
for(int i=0;i<n;i++)
{
m[arr1[i]]++;
m[arr2[i]]++;
m[arr3[i]]++;
}
vector<int> res;
for(map<int,int>::iterator ite=m.begin();ite!=m.end();ite++)
{
if(ite->second==3)
{
res.push_back(ite->first);
}
}
return res;
}
};

5080.查找两棵二叉搜索树之和

解法1:map

用map存第一棵树对应的target-root->val值,第二颗数查找这个值,若找到直接返回true

即转化为类似的两数之和

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 {
map<int,int> m;
int tar;
public:
bool twoSumBSTs(TreeNode* root1, TreeNode* root2, int target) {
tar=target;
midbfs(root1);
return midbfs2(root2);
}
void midbfs(TreeNode *root)
{
if(root!=NULL)
{
midbfs(root->left);
m[tar-root->val]++;
midbfs(root->right);
}
}
bool midbfs2(TreeNode *root)
{
if(root!=NULL)
{
if(m[root->val]!=0)
return true;
return midbfs2(root->left)||midbfs2(root->right);
}
return false;
}
};

5081.步进数

解法1:预处理+二分

找规律,发现除0-9这10个数,后面的步进数都是从1开始向后遍历加上一位和末位相差1的数,

例如根据1可以向后10,12,根据2可以向后添加21,23。根据这个规律我们就能快速找到所有小于high的步进数。

现在我们要找到从那个步进数开始是大于low的,这样我们可以采用二分查找,找到第一个大于low的或找到步进数的最后一位。

后处理判断找到的值是否大于low,

1.若小于表示在low-high内没有步进数

2.若大于将找到的步进数数组从left到结束添加到结果数组

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
31
32
33
34
35
36
37
38
39
40
41
42
class Solution {
public:
vector<int> countSteppingNumbers(int low, int high) {
vector<int> res;
for(int i=0;i<=9;i++){res.push_back(i);}
int i=1,cur,k,temp;
while(1)
{
cur=res[i];
k=cur%10;
if(k-1>=0)
{
temp=cur*10+k-1;
if(temp>high)
break;
res.push_back(temp);
}
if(k+1<=9)
{
temp=cur*10+k+1;
if(temp>high)
break;
res.push_back(temp);
}
i++;
}
int left=0,right=res.size()-1;
while(left<right)
{
int mid=left+(right-left)/2;
if(res[mid]<low)
{
left=mid+1;
}
else right=mid;
}
vector<int> anb;
if(res[left]<low) return anb;
vector<int> ans(res.begin()+left,res.end());
return ans;
}
};

5099.验证回文字符串 III

解法1:动态规划

问题的本质就是找一个最长回文子序列。

思路:

先创建一个字符串t是s的翻转字符串。这样我们就可以将问题转为找s和t的最长公共子序列

若最长公共子序列长度>=n-k则符合要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
bool isValidPalindrome(string s, int k) {
int n=s.size();
string t=s;
reverse(t.begin(),t.end());
vector<vector<int>> dp(n+1,vector<int>(n+1,0));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(s[i]==t[j]) dp[i+1][j+1]=dp[i][j]+1;
else dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
}
}
return dp[n][n]>=n-k;
}
};