letcode第319场周赛

letcode第319场周赛

6233. 温度转换

给你一个四舍五入到两位小数的非负浮点数 celsius 来表示温度,以 摄氏度Celsius)为单位。

你需要将摄氏度转换为 开氏度Kelvin)和 华氏度Fahrenheit),并以数组 ans = [kelvin, fahrenheit] 的形式返回结果。

返回数组 ans 。与实际答案误差不超过 10-5 的会视为正确答案**。**

注意:

  • 开氏度 = 摄氏度 + 273.15
  • 华氏度 = 摄氏度 * 1.80 + 32.00

示例 1 :

输入:celsius = 36.50
输出:[309.65000,97.70000]
解释:36.50 摄氏度:转换为开氏度是 309.65 ,转换为华氏度是 97.70 。

示例 2 :

输入:celsius = 122.11
输出:[395.26000,251.79800]
解释:122.11 摄氏度:转换为开氏度是 395.26 ,转换为华氏度是 251.798 。

提示:

  • 0 <= celsius <= 1000

水题

class Solution {
public:
    vector<double> convertTemperature(double celsius) {
        double a,b;
        a=b=celsius;
        return {a+273.15,b*1.8+32};
    }
};

6234. 最小公倍数为 K 的子数组数目

难度中等2收藏分享切换为英文接收动态反馈

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 nums子数组 中满足 元素最小公倍数为 k 的子数组数目。

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

数组的最小公倍数 是可被所有数组元素整除的最小正整数。

示例 1 :

输入:nums = [3,6,2,7,1], k = 6
输出:4
解释:以 6 为最小公倍数的子数组是:
- [3,6,2,7,1]
- [3,6,2,7,1]
- [3,6,2,7,1]
- [3,6,2,7,1]

示例 2 :

输入:nums = [3], k = 2
输出:0
解释:不存在以 2 为最小公倍数的子数组。

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i], k <= 1000

暴力

我是真没想到暴力能过,卡贼久,服了。

记录区间内元素可以被k整除且公倍数为k的所有最大子数组,最后从每个区间开始暴力枚举起点有多少个满足条件的区间

long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
long long lcm(long long a,long long b)
{
    return a/gcd(a,b)*b;
}

class Solution {
public:
    int subarrayLCM(vector<int>& nums, int k) {
        int l=0,r=0;
        vector<vector<int>>edge;
        long long lc=1;
        while(r<nums.size())
        {
            if(k%nums[r]==0)
            {
                lc=lcm(nums[r],lc);
                r++;
            }
            else
            {
                 if(lc==k)
                edge.push_back({l,r});
                r++;
                l=r;
                lc=1;
            }
        }
        if(lc==k)
            edge.push_back({l,r});
       // for(int i=0;i<edge.size();i++)
            //cout<<edge[i][0]<<" "<<edge[i][1]<<endl;
        int ans=0;
        lc=1;
        for(int i=0;i<edge.size();i++)
        {
            for(int j=edge[i][0];j<edge[i][1];j++)
            {
                lc=lcm(nums[j],lc);
                if(lc==k)
                    ans+=edge[i][1]-j,lc=1,edge[i][0]+=1,j=edge[i][0]-1;
            }
        }
        return ans;
    }
};

优化

最小公倍数要么不变,要么至少 \times 2×2,因此在遍历 \textit{nums}nums 的同时,维护最小公倍数集合(数组),这至多有 O(lgk) 个。

注意最小公倍数必须是 k 的因子

详细思路看灵神的帖子

6235. 逐层排序二叉树所需的最少操作数目

难度中等5收藏分享切换为英文接收动态反馈

给你一个 值互不相同 的二叉树的根节点 root

在一步操作中,你可以选择 同一层 上任意两个节点,交换这两个节点的值。

返回每一层按 严格递增顺序 排序所需的最少操作数目。

节点的 层数 是该节点和根节点之间的路径的边数。

示例 1 :

输入:root = [1,4,3,7,6,8,5,null,null,null,null,9,null,10]
输出:3
解释:
- 交换 4 和 3 。第 2 层变为 [3,4] 。
- 交换 7 和 5 。第 3 层变为 [5,6,8,7] 。
- 交换 8 和 7 。第 3 层变为 [5,6,7,8] 。
共计用了 3 步操作,所以返回 3 。
可以证明 3 是需要的最少操作数目。

示例 2 :

输入:root = [1,3,2,7,6,5,4]
输出:3
解释:
- 交换 3 和 2 。第 2 层变为 [2,3] 。 
- 交换 7 和 4 。第 3 层变为 [4,6,5,7] 。 
- 交换 6 和 5 。第 3 层变为 [4,5,6,7] 。
共计用了 3 步操作,所以返回 3 。 
可以证明 3 是需要的最少操作数目。

示例 3 :

输入:root = [1,2,3,4,5,6]
输出:0
解释:每一层已经按递增顺序排序,所以返回 0 。

提示:

  • 树中节点的数目在范围 [1, 105]
  • 1 <= Node.val <= 105
  • 树中的所有值 互不相同

要是没遇见过怎么求最少交换次数,还真做不出,后面又看了半天证明才明白

证明链接:

/**
 * 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) {}
 * };
 */
struct x{
    int val,depth;
};
struct y{
    TreeNode*root;
    int depth;
};
int getMinSwaps(vector<int> &nums){
    //排序
    vector<int> nums1(nums);
    sort(nums1.begin(),nums1.end());
    unordered_map<int,int> m;
    int len = nums.size();
    for (int i = 0; i < len; i++){
        m[nums1[i]] = i;//建立每个元素与其应放位置的映射关系
    }
    int loops = 0;//循环节个数
    vector<bool> flag(len,false);
    //找出循环节的个数
    for (int i = 0; i < len; i++){
        if (!flag[i]){//已经访问过的位置不再访问
            int j = i;
            while (!flag[j]){
                flag[j] = true;
                j = m[nums[j]];//原序列中j位置的元素在有序序列中的位置
            }
            loops++;
        }
    }
    return len - loops;
}
class Solution {
public:
    int minimumOperations(TreeNode* root) {
       queue<y>q;
      vector<vector<int>>nums(100000);
        q.push({root,0});
        int depth=0;
        while(!q.empty())
        {
            y r=q.front();
            nums[r.depth].push_back(r.root->val);
            depth=r.depth;
            q.pop();
            if(r.root->left)
            q.push({r.root->left,r.depth+1});
            if(r.root->right)
            q.push({r.root->right,r.depth+1});
        }
        int ans=0;
        for(int i=0;i<=depth;i++)
            ans+=getMinSwaps(nums[i]);
        return ans;
    }
};

6236. 不重叠回文子字符串的最大数目

难度困难12收藏分享切换为英文接收动态反馈

给你一个字符串 s 和一个 整数 k

从字符串 s 中选出一组满足下述条件且 不重叠 的子字符串:

  • 每个子字符串的长度 至少k
  • 每个子字符串是一个 回文串

返回最优方案中能选择的子字符串的 最大 数目。

子字符串 是字符串中一个连续的字符序列。

示例 1 :

输入:s = "abaccdbbd", k = 3
输出:2
解释:可以选择 s = "abaccdbbd" 中斜体加粗的子字符串。"aba" 和 "dbbd" 都是回文,且长度至少为 k = 3 。
可以证明,无法选出两个以上的有效子字符串。

示例 2 :

输入:s = "adbcda", k = 2
输出:0
解释:字符串中不存在长度至少为 2 的回文子字符串。

提示:

  • 1 <= k <= s.length <= 2000
  • s 仅由小写英文字母组成

字符串hash判断回文+dp

unsigned long long fun(vector<unsigned long long>& hash, int i, int j, vector<unsigned long long>&p)
{
    return hash[j] - hash[i - 1] * p[j - i + 1];
}
int maxPalindromes(string s, int k) {
    vector<unsigned long long>hash(s.size() + 1), p(s.size() + 1), hash1(s.size() + 1);
    p[0] = 1;
    for (int i = 1, j = s.size() - 1; i <= s.size(); i++, j--)
    {
        hash[i] = hash[i - 1] * base + s[i - 1] - 'a';
        p[i] = p[i - 1] * base;
        hash1[i] = hash1[i - 1] * base + s[j] - 'a';
    }
    vector<int>dp2(s.size() + 1, 0);
    for (int i = 1; i <= s.size(); i++)
    {
        for (int j = i; j <= s.size(); j++)
        {
            if (j - i + 1 >= k && fun(hash,i,j,p) == fun(hash1,s.size()-j+1,s.size()-i+1,p))
                dp2[j] = max(dp2[i - 1] + 1, dp2[j]);
            else
                dp2[j] = max(dp2[j - 1],dp2[j]);
        }
    }
  /*  for (int i = 0; i <= s.size(); i++)
        cout << dp2[i] << " ";*/
    return dp2[s.size()];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值