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()];
}