LeetCode 第320场周赛

LeetCode 第320场周赛

6241. 数组中不等三元组的数目

三个循环暴力

C++

class Solution {
public:
    int unequalTriplets(vector<int>& nums) {
        int n=nums.size(),ans=0;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                for(int k=j+1;k<n;k++){
                    if(nums[i]!=nums[j]&&nums[i]!=nums[k]&&nums[j]!=nums[k]) ans++;
                }
            }
        }
        return ans;
    }
};

Python

class Solution:
    def unequalTriplets(self, nums: List[int]) -> int:
        n=len(nums)
        ans=0
        for i in range(n):
            for j in range(i+1,n):
                for k in range(j+1,n):
                    if nums[i]!=nums[j] and nums[i]!=nums[k] and nums[j]!=nums[k]:
                        ans+=1
        
        return ans

6242. 二叉搜索树最近节点查询

这里肯定是要用到二叉树的性质来写的,但是我直接没有思考当成二叉树来做,把所有节点拿到,然后用二分查。

C++

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> vec;
    void dfs(TreeNode* root){
        if(root==nullptr) return;
        dfs(root->left);
        vec.push_back(root->val);
        dfs(root->right);
    }
    vector<vector<int>> closestNodes(TreeNode* root, vector<int>& q) {
        dfs(root);
        sort(vec.begin(),vec.end());
        int n=vec.size();
        vector<vector<int> >res;
        for(auto &x:q){
            int pos=lower_bound(vec.begin(),vec.end(),x)-vec.begin();
            if(pos>=0&&pos<n&&vec[pos]==x){
                res.push_back({x,x});
            }
            else{
                int mi=-1,mx=-1;
                if(pos>=1) mi=vec[pos-1];
                if(pos>=n) mx=-1;
                else mx=vec[pos];
                res.push_back({mi,mx});
            }
        }
        return res;
    }
};

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def closestNodes(self, root: Optional[TreeNode], queries: List[int]) -> List[List[int]]:
        arr=[]

        def dfs(root:Optional[TreeNode]):
            if root is None:
                return
            dfs(root.left)
            arr.append(root.val)
            dfs(root.right)
        
        dfs(root)
        ans=[]
        for x in queries:
            pos=bisect_right(arr,x)
            min=arr[pos-1] if pos else -1
            pos= bisect_left(arr, x)
            max=arr[pos] if pos<len(arr) else -1
            ans.append([min,max])

        return ans

6243. 到达首都的最少油耗

思维+树遍历

中午的时候实在没想明白,没有转化题目的意思

把整个地图看成0为根节点的树,显然从树的叶子节点往上接人,这样油耗更低。无论车子座位有没有限制这都是成立的。

那么如果当前节点为u,它的子树有 S u S_{u} Su个节点,那么这个这些人至少需要 S u + s e a t s − 1 s e a t s \frac{S{u}+seats-1}{seats} seatsSu+seats1辆车才能送往0出。

class Solution:
    def minimumFuelCost(self, roads: List[List[int]], seats: int) -> int:
        ans=0
        g = [[] for _ in range(len(roads)+1)]
        for x,y in roads:
            g[x].append(y)
            g[y].append(x)
        
        def dfs(u:int,fa:int) -> int:
            ret=1
            for v in g[u]:
                if v==fa: continue
                t=dfs(v,u)
                ret+=t
                nonlocal ans;
                ans+=(seats-1+t)//seats
            return ret
        
        dfs(0,-1)

        return ans
            

6244. 完美分割的方案数

思路:递推DP

DP表示:

dp[i][j]表示前i个字符,分成j段的方案数。

DP转移方程就有:

dp[i][j]=sum(dp[1][j-1]~dp[i-minlength][j-1]) // 前提是合法,如果第i个字符不能满足分割,那么这个也不用枚举了

如果直接枚举的话时间复杂度 O ( n 2 k ) O(n^2k) O(n2k) 1000显然会超时。

可以发现每次要求都从j-1段的,1~i-minlength的和,可以对f[i][j]做前缀和。

class Solution {
public:
    bool chk(char s){
        return s=='2'||s=='3'||s=='5'||s=='7';
    }
    int beautifulPartitions(string s, int k, int minLensumth) {
        if(!chk(s[0])) return 0;
        int n=s.size();
        const int mod=1e9+7;

        long long f[n+1][k+1],sum[n+1][k+1];
        
        memset(f,0,sizeof(f));
        memset(sum,0,sizeof(sum));
        f[0][0]=1;//如果空串分割0次答案为1
        sum[0][0]=1;

        for(int i=1;i<=n;i++){
            if(i>=minLensumth && !chk(s[i-1]) && (i==n|| chk(s[i])))//分割之后的下一个字符为质数,才可以分割
            for(int j=1;j<=k;j++){// 从i-minlensumth开始求和到i,j-1段的
                f[i][j]=sum[i-minLensumth][j-1];
            }

            for(int j=0;j<=k;j++){
                sum[i][j]=(sum[i-1][j]+f[i][j])%mod;
            }
        }
        return f[n][k];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万伏小太阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值