LeetCode,第377场周赛,个人题解

目录

100148.最小数字游戏

题目描述

思路分析

代码详解

100169.移除栅栏得到的正方形田地的最大面积

题目描述

思路分析

代码详解

100156.转换字符串的最小成本I

题目描述

思路分析

代码详解

100158.转换字符串的最小成本II

题目描述

思路分析

代码详解


100148.最小数字游戏

题目描述

你有一个下标从 0 开始、长度为 偶数 的整数数组 nums ,同时还有一个空数组 arr 。Alice 和 Bob 决定玩一个游戏,游戏中每一轮 Alice 和 Bob 都会各自执行一次操作。游戏规则如下:

  • 每一轮,Alice 先从 nums 中移除一个 最小 元素,然后 Bob 执行同样的操作。
  • 接着,Bob 会将移除的元素添加到数组 arr 中,然后 Alice 也执行同样的操作。
  • 游戏持续进行,直到 nums 变为空。

返回结果数组 arr 。

思路分析

小根堆直接模拟

代码详解

class Solution {
public:vector<int> numberGame(vector<int>& nums) {priority_queue<int,vector<int>,greater<int>> pq{nums.begin() , nums.end()};vector<int> ret;int x , y;while(pq.size()){y = pq.top();pq.pop();x = pq.top() , pq.pop();ret.push_back(x);ret.push_back(y);}return ret;}
};

100169.移除栅栏得到的正方形田地的最大面积

题目描述

有一个大型的 (m - 1) x (n - 1) 矩形田地,其两个对角分别是 (1, 1) 和 (m, n) ,田地内部有一些水平栅栏和垂直栅栏,分别由数组 hFences 和 vFences 给出。

水平栅栏为坐标 (hFences[i], 1) 到 (hFences[i], n),垂直栅栏为坐标 (1, vFences[i]) 到 (m, vFences[i]) 。

返回通过 移除 一些栅栏(可能不移除)所能形成的最大面积的 正方形 田地的面积,或者如果无法形成正方形田地则返回 -1

由于答案可能很大,所以请返回结果对 109 + 7 取余 后的值。

注意:田地外围两个水平栅栏(坐标 (1, 1) 到 (1, n) 和坐标 (m, 1) 到 (m, n) )以及两个垂直栅栏(坐标 (1, 1) 到 (m, 1) 和坐标 (1, n) 到 (m, n) )所包围。这些栅栏 不能 被移除。

思路分析

先对两个方向栅栏进行排序,然后哈希表记录所有水平可能间隔

枚举垂直可能间隔,如果已经在哈希表存在,则为可能答案,维护答案的最大值即可

代码详解

class Solution
{
public:const int MOD = 1e9 + 7;int maximizeSquareArea(int m, int n, vector<int> &hFences, vector<int> &vFences){unordered_set<int> hash;hFences.emplace_back(m);vFences.emplace_back(n);sort(hFences.begin(),hFences.end());sort(vFences.begin(),vFences.end());int n1 = hFences.size(), n2 = vFences.size(), x, ans = 0;for (int i = 0; i < n1; i++){x = hFences[i];hash.insert(x - 1);for (int j = i - 1; j >= 0; j--)hash.insert(x - hFences[j]);}for (int i = 0; i < n2; i++){x = vFences[i];if (hash.count(x - 1))ans = max(ans, x - 1);for (int j = i - 1; j >= 0; j--)if (hash.count(x - vFences[j]))ans = max(ans, x - vFences[j]);}return ans ? (((long long)ans * ans) % MOD) : -1;}
};

100156.转换字符串的最小成本I

题目描述

给你两个下标从 0 开始的字符串 source 和 target ,它们的长度均为 n 并且由 小写 英文字母组成。

另给你两个下标从 0 开始的字符数组 original 和 changed ,以及一个整数数组 cost ,其中 cost[i] 代表将字符 original[i] 更改为字符 changed[i] 的成本。

你从字符串 source 开始。在一次操作中,如果 存在 任意 下标 j 满足 cost[j] == z  、original[j] == x 以及 changed[j] == y 。你就可以选择字符串中的一个字符 x 并以 z 的成本将其更改为字符 y 。

返回将字符串 source 转换为字符串 target 所需的 最小 成本。如果不可能完成转换,则返回 -1 。

注意,可能存在下标 i 、j 使得 original[j] == original[i] 且 changed[j] == changed[i] 。

思路分析

可以直接转换的字符之间可以建立一条有向边,那么我们可以预处理一张有向图,然后跑一边floyd,比对原字符串和目标字符串,如果相同则不做处理

如果不同且有路,那么答案加上路径长度

如果不同且没路,那么就直接返回-1

代码详解

class Solution
{
public:long long minimumCost(string source, string target, vector<char> &original, vector<char> &changed, vector<int> &cost){long long ret = 0;int n = original.size();vector<vector<int>> minc(26 , vector<int>(26,INT_MAX));for (int i = 0; i < n; i++)minc[original[i] - 'a'][changed[i] - 'a'] = min(minc[original[i] - 'a'][changed[i] - 'a'],cost[i]);for (int k = 0; k < 26; k++)for (int i = 0; i < 26; i++)for (int j = 0; j < 26; j++)if (minc[i][j] - minc[i][k] > minc[k][j])minc[i][j] = minc[i][k] + minc[k][j];for (int i = 0, len = source.size(); i < len; i++)if (source[i] == target[i])continue;else{if (minc[source[i] - 'a'][target[i] - 'a'] == INT_MAX)return -1;ret += minc[source[i] - 'a'][target[i] - 'a'];}return ret;}
};

100158.转换字符串的最小成本II
 

题目描述

给你两个下标从 0 开始的字符串 source 和 target ,它们的长度均为 n 并且由 小写 英文字母组成。

另给你两个下标从 0 开始的字符串数组 original 和 changed ,以及一个整数数组 cost ,其中 cost[i] 代表将字符串 original[i] 更改为字符串 changed[i] 的成本。

你从字符串 source 开始。在一次操作中,如果 存在 任意 下标 j 满足 cost[j] == z  、original[j] == x 以及 changed[j] == y ,你就可以选择字符串中的 子串 x 并以 z 的成本将其更改为 y 。 你可以执行 任意数量 的操作,但是任两次操作必须满足 以下两个 条件 之一 :

  • 在两次操作中选择的子串分别是 source[a..b] 和 source[c..d] ,满足 b < c   d < a 。换句话说,两次操作中选择的下标 不相交 
  • 在两次操作中选择的子串分别是 source[a..b] 和 source[c..d] ,满足 a == c  b == d 。换句话说,两次操作中选择的下标 相同 

返回将字符串 source 转换为字符串 target 所需的 最小 成本。如果不可能完成转换,则返回 -1 。

注意,可能存在下标 i 、j 使得 original[j] == original[i] 且 changed[j] == changed[i] 。

思路分析

和上一道题类似的思路,上一题对字符建图,这道题对字符串建图

关键在于如何快速获取字符串,可以选择字符哈希,这里我用的字典树,不过比赛的时候被卡常了,赛后加了个关闭输入输出同步然后过了

具体就是把可转换字符串都插入到字典树,对应单词结尾的字典树节点编号是可以作为字符串的映射的,为了跑floyd就把字典树节点编号再离散化一下

这样得到了最多200个节点的图,完全可以跑floyd

然后对于熟悉这种字符串转换的很容易想到动态规划进一步处理

我们规定dp[i]为下标i 到 n - 1转换成本

然后我们找从下标i开始的可转换子串,结束下标为j,那么dp[i] = min(dp[i] , dp[j + 1] + dist[][])

那么如果source[i] == target[i] ,dp[i]初始化为dp[i + 1]

之所以倒序dp是因为用了字典树存储

代码详解

class Solution
{
public:Solution(){ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);}int nodes[200010][26], id[200010] , idx;long long inf = 0x3f3f3f3f3f3f3f3f;int insert(const string &s){int cur = 0;for (char c : s){if (nodes[cur][c - 'a'] == -1)nodes[cur][c - 'a'] = idx++;cur = nodes[cur][c - 'a'];}return cur;};long long minimumCost(string source, string target, vector<string> &original, vector<string> &changed, vector<int> &cost){int n = original.size() * 2, x, y;long long d[n][n];memset(d, 0x3f, sizeof(d));memset(id, -1, sizeof(id));memset(nodes, -1, sizeof(nodes));idx = 1;int tot = 0;for (int i = 0; i < original.size(); ++i){x = insert(original[i]), y = insert(changed[i]);if(id[x] == -1) id[x] = tot++;if(id[y] == -1) id[y] = tot++;x = id[x] , y = id[y];d[x][y] = min(d[x][y], (long long)cost[i]);}for (int k = 0; k < tot; ++k)for (int i = 0; i < tot; ++i)for (int j = 0; j < tot; ++j)if (d[i][j] - d[i][k] > d[k][j])d[i][j] = min(d[i][j], d[i][k] + d[k][j]);n = source.size();vector<long long> dp(n + 1, inf);dp[n] = 0;for (int i = n - 1; i >= 0; i--){if (source[i] == target[i])dp[i] = dp[i+1];x = y = 0;for(int j = i ; j < n ; j++){x = nodes[x][source[j]-'a'],y = nodes[y][target[j]-'a'];if(y==-1||x==-1) break;if(id[x]==-1||id[y]==-1) continue;dp[i] = min(dp[i] , dp[j+1] + d[id[x]][id[y]]);}}return dp[0] == inf ? -1 : dp[0];}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

for each....in、for in、for of

一、一般的遍历数组的方法: var array [1,2,3,4,5,6,7]; for (var i 0; i < array.length; i) { console.log(i,array[i]); } 二、用for in的方遍历数组 for(let index in array) { console.log(index,array[index]); }; 三、forEach array.forEach(v>{ cons…

Vue cli3.0创建Vue项目

创建Vue项目 在要创建项目的文件夹下面打开Powershell窗口 输入命令 vue create 项目名称 选择第二项 回车后 选择是否使用历史路由 no 回车 选择 Less 回车 选择第三个 回车 选择第一个 回车 选择第一个 回车 是否保存模板 选择no 完成啦 完成

文件内容的输出io

package bbb; import java.io.*; public class ccc {public static void main(String[]args) throws IOException{ File filenew File("d:/1data.txt"); FileOutputStream outnew FileOutputStream(file); byte buy[]"12345abcdef#%&*软件工程".getByt…

看完后完全了解 Vue 2.0 和 Vue 3.0 的区别

1.数据的双向绑定 Vue2.0使用Object.defineProperty 原理&#xff1a;通过使用 Object.defineProperty 来劫持对象属性的 geter 和 seter 操作&#xff0c;当数据发生改变发出通知 代码&#xff1a; 1 <!DOCTYPE html>2 <html lang"en">3 <head>4…

channels2.X 学习笔记

- No module named asgiref.sync 报错解决&#xff1a; # 报错原因&#xff1a; """ django版本过低&#xff0c; 卸载最新版本的 channels 使用2.x 版本的 """ pip3 uninstall channels - 安装&#xff1a; """ Django 1.11.15 …

风格迁移学习笔记

风格迁移大作业 学习规划 跑通一份代码&#xff01;&#xff01;&#xff01;&#xff08;done&#xff09;对照代码、Blog和论文理解相应的算法过程规划下一步&#xff0c;修改代码&#xff08;done&#xff09;&#xff0c;实现预计功能&#xff08;done&#xff09;调参&…

Netty源码分析第5章(ByteBuf)----第5节: directArena分配缓冲区概述

Netty源码分析第5章(ByteBuf)---->第5节: directArena分配缓冲区概述 Netty源码分析第五章: ByteBuf 第五节: directArena分配缓冲区概述 上一小节简单分析了PooledByteBufAllocator中, 线程局部缓存和arean的相关逻辑, 这一小节简单分析下directArena分配缓冲区的相关过程 …

uni-app(从零开始)

uni-app&#xff08;从零开始&#xff09; uni-app 是什么&#xff1f; uniapp 就是使用Vue.js技术开发所有前端框架的跨端框架uniapp 就是可以将一套代码 发布到多个平台 uniapp 和 Vue 的关系&#xff1f; uniapp是基于vue进行开发&#xff0c;继承了Vue的特性和语法在开…

Remote desktop manager共享账号

因为多个远程机器&#xff0c;是会用了域账号进行登录的。而域账号的密码&#xff0c;三个月之后&#xff0c;密码强制过期 添加一个新的entry&#xff0c;类型是Credential Entry&#xff0c;然后选择用户名/密码 在remote desktop编辑的页面&#xff0c;Credentials选择Crede…

bzoj4403:序列统计

我好傻啊 题目 先来看看长度只能为\(n\)的情况 那么答案非常显然是\(\binom{mn-1}{n}\) 其中\(mR-L1\) 因为我们要构造一个非降序列&#xff0c;显然可能一个数会被选择多次&#xff0c;组合非常不好做&#xff0c;于是我们可以把每一个数的下标加上其对应的下标那么现在的值域…

Mui常用的方法

中对话框 语法&#xff1a;mui.confirm 用法 mui.confirm("确认要切换角色&#xff1f;", "提示", btnArray, function(e) {if(e.index 1) {} else {}});组件名作用alert警告框confirm确认框prompt输入对话框toast消息提示框&#xff08;自动消失&#x…

sudo: pip:找不到命令

https://blog.csdn.net/fcku_88/article/details/84191288转载于:https://www.cnblogs.com/xxswkl/p/11012709.html

java ListMapString,Object遍历的方法

java List<Map<String,Object>遍历的方法 public class Test {public static void main(String[] args) {List<Map<String, Object>> listMaps new ArrayList<Map<String, Object>>();Map<String, Object> map1 new HashMap<Strin…

vue如何更换网页标签的logo

Vue2 版本更换图标 在我们项目的根目录下面去添加或者替换 favicon.icon文件 找到我们的 build 文件夹下面的这两个文件 进行如下配置 favicon: resolveApp(’./favicon.ico’) 刷新后发现并没有什么效果 莫慌 最后一步 重启项目 改变端口 如果重启后还没有起到作用的话就…

Java并发编程的艺术(十)——Java中的锁(5)

1. LockSupport工具 1.1 LockSupport的作用 当需要阻塞或唤醒一个线程的时候&#xff0c;都会使用LockSupport工具类来完成相应工作。LockSupport定义了一组公共的静态方法&#xff0c;这些方法提供了做基本的线程阻塞和唤醒功能。 1.2 LockSupport提供的阻塞和唤醒方法 方法描…

运动-模拟返回顶部

第一步&#xff1a;获取底部的那个按钮对象&#xff0c;默认的情况下那个按钮对象是不可见的。可见的条件的是滚轮距离顶部有距离。 var oBtndocument.getElementById(btn1); 第二步&#xff1a;添加滚轮事件。 (1). 获取滚轮距离顶部的距离。如果距离大于0&#xff0c;就将按钮…

《JavaScript高级程序设计》笔记总结

在北京上班的我每天在上下班路上的时间总共是两个半小时&#xff0c;为了充实这两个多小时的时间&#xff0c;我便花了银子换得了下面这个宝贝 本书内容&#xff08;引用书中前言&#xff09; 本书提供了JavaScript开发人员必须掌握的内容&#xff0c;全面涵盖了JavaScript的…

Task执行多次

项目中&#xff0c;曾经出现过启动时数据库连接数瞬间增大&#xff0c;当时并没有注意该问题。 后期&#xff0c;由于Task任务多次执行&#xff0c;才着手查看这个问题&#xff0c;经排查&#xff0c;由于tomcat中webapp配置多次&#xff0c;导致webapp被扫描多次&#xff08;配…

ES6 的新特性总结

ES6 的新特性总结 关于声明变量 由 var 变成 let 和 const 区别&#xff1a; var声明的变量会挂载到window上&#xff0c;let和const声明的变量不会var声明的变量存在变量提升&#xff0c;而let和const声明的变量不存在变量提升let和const声明的变量形成块级作用域在同一作…

递推(一):递推法的基本思想

所谓递推&#xff0c;是指从已知的初始条件出发&#xff0c;依据某种递推关系&#xff0c;逐次推出所要求的各中间结果及最后结果。其中初始条件或是问题本身已经给定&#xff0c;或是通过对问题的分析与化简后确定。 利用递推算法求问题规模为n的解的基本思想是&#xff1a;当…