LeetCode双周赛10

Leetcode双周赛10

5079.三个有序数组的交集

给出三个均为 严格递增排列 的整数数组 arr1,arr2 和 arr3。

返回一个由 仅 在这三个数组中 同时出现 的整数所构成的有序数组。

示例:

输入: arr1 = [1,2,3,4,5], arr2 = [1,2,5,7,9], arr3 = [1,3,4,5,8]
输出: [1,5]
解释: 只有 1 和 5 同时在这三个数组中出现.

提示:

1 <= arr1.length, arr2.length, arr3.length <= 1000
1 <= arr1[i], arr2[i], arr3[i] <= 200

数据范围只有1000,直接暴力的(O(n^3))匹配。当然也可以用二分查找将复杂度降到(O(n(logn)^2)),不过没有必要。

int tmp[1005];
class Solution {
public:
    vector<int> arraysIntersection(vector<int>& arr1, vector<int>& arr2, vector<int>& arr3)
    {
        int cnt=0;
        for(int i=0;i<arr1.size();i++)
        {
            for(int j=0;j<arr2.size();j++)
            {
                if(arr1[i]==arr2[j])
                {
                    for(int k=0;k<arr3.size();k++)
                    {
                        if(arr2[j]==arr3[k])
                        {
                            cnt++;
                            tmp[cnt]=arr3[k];
                        }       
                    }
                }
            }
        }
        vector<int> ans;
        for(int i=1;i<=cnt;i++)
        {
            ans.push_back(tmp[i]);
        }
        return ans;
    }
};

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

给出两棵二叉搜索树,请你从两棵树中各找出一个节点,使得这两个节点的值之和等于目标值 Target。

如果可以找到返回 True,否则返回 False。

示例 1:

输入:root1 = [2,1,4], root2 = [1,0,3], target = 5
输出:true
解释:2 加 3 和为 5 。

示例 2:

输入:root1 = [0,-10,10], root2 = [5,1,7,0,2], target = 18
输出:false

提示:

每棵树上最多有 5000 个节点。
-10^9 <= target, node.val <= 10^9

只有5000个节点,也就是说暴力匹配完全可行(暴力双周赛),用dfs搜出每个节点的值然后再进行比较。

(我写的比较丑)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
int tree1[5001];
int tree2[5001];
int cnt1=0;
int cnt2=0;
void dfs1(TreeNode root)
{
    cnt1++;
    tree1[cnt1]=root.val;
    if(root.left!=NULL)
    {
        dfs1(*root.left);
    }
    if(root.right!=NULL)
    {
        dfs1(*root.right);
    }
    return ;
}
void dfs2(TreeNode root)
{
    cnt2++;
    tree2[cnt2]=root.val;
    if(root.left!=NULL)
    {
        dfs2(*root.left);
    }
    if(root.right!=NULL)
    {
        dfs2(*root.right);
    }
    return ;
}
class Solution {
public:
    bool twoSumBSTs(TreeNode* root1, TreeNode* root2, int target)
    {
        dfs1(*root1);
        dfs2(*root2);
        for(int i=1;i<=cnt1;i++)
        {
            for(int j=1;j<=cnt2;j++)
            {
                if(tree1[i]+tree2[j]==target)
                {
                    return true;
                }
            }
        }
        return false;
    }
};

5081.步进数

如果一个整数上的每一位数字与其相邻位上的数字的绝对差都是 1,那么这个数就是一个「步进数」。

例如,321 是一个步进数,而 421 不是。

给你两个整数,low 和 high,请你找出在 [low, high] 范围内的所有步进数,并返回 排序后 的结果。

示例:

输入:low = 0, high = 21
输出:[0,1,2,3,4,5,6,7,8,9,10,12,21]

提示:

0 <= low <= high <= 2 * 10^9

既然数据量达到了2*10^9那么就不要考虑暴力枚举了,直接按位枚举进行构造,从低位开始,到高位结束,中间每次判断。

int n;
int cnt;
int tans[1000005];
void dfs(int l,int r,long long tp,int thisn,int idx)
{
    if(l<=tp && r>=tp)
    {
        cnt++;
        tans[cnt]=tp;
    }
    if(idx>n)
    {
        return ;
    }
    if(thisn+1<10)
    {
        dfs(l,r,tp*10+thisn+1,thisn+1,idx+1);
    }
    if(thisn-1>=0)
    {
        dfs(l,r,tp*10+thisn-1,thisn-1,idx+1);
    }
    return ;
}
class Solution {
public:
    vector<int> countSteppingNumbers(int low, int high)
    {
        memset(tans,0,sizeof(tans));
        cnt=0;
        int tmp=high;
        n=0;
        while(tmp)
        {
            tmp/=10;
            n++;
        }
        for(int i=1;i<=9;i++)
        {
            dfs(low,high,i,i,1);
        }
        sort(tans+1,tans+1+cnt);
        vector<int> ans;
        if(low==0)
        {
            ans.push_back(0);
        }
        for(int i=1;i<=cnt;i++)
        {
            ans.push_back(tans[i]);
        }
        return ans;
    }
};

5099.验证回文字符串 III

给出一个字符串 s 和一个整数 k,请你帮忙判断这个字符串是不是一个「K 回文」。

所谓「K 回文」:如果可以通过从字符串中删去最多 k 个字符将其转换为回文,那么这个字符串就是一个「K 回文」。

示例:

输入:s = "abcdeca", k = 2
输出:true
解释:删除字符 “b” 和 “e”。

提示:

1 <= s.length <= 1000
s 中只含有小写英文字母
1 <= k <= s.length

这道题最关键的问题在于如何判断是回文串,如果每尝试删除一次再判断那么复杂度肯定是接受不了的。我们换一种思路,先判断回文串再来考虑如何删除元素。我们可以将原串进行反转,这样两个字符串就可以进行匹配哪些位的字符相同,因为这两个字符串是相反的也就是说位置相同的两个字符其实是原串中的镜像关系。

这样我们再来进行删除步骤,将相同位置不同的字符删掉就可以构造一个回文串。这样问题就简化了,我们只需要求出有多少字符是不匹配的再和k比较就可以了,要求不匹配先求匹配,可以用LCS直接求出匹配再比较就行了。

char str[1005];
int f[1005][1005];
class Solution {
public:
    bool isValidPalindrome(string s, int k)
    {
        memset(str,' ',sizeof(str));
        memset(f,0,sizeof(f));
        int n;
        n=s.size();
        for(int i=0;i<n;i++)
        {
            str[i]=s[n-1-i];
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(str[i-1]==s[j-1])
                {
                    f[i][j]=f[i-1][j-1]+1;
                }
                else
                {
                    f[i][j]=max(f[i-1][j],f[i][j-1]);
                }
            }
        }
        if(f[n][n]+k>=n)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

暴力大赛,除最后一题外都太简单了,而最后一题只是需要动动脑筋而不需要掌握太高深的算法。

原文地址:https://www.cnblogs.com/Heizesi/p/11631993.html