【性能优化】 【回溯】 【字符串】1307. 口算难题

作者推荐

视频算法专题

本文涉及知识点

数学 回溯 字符串 性能优化

LeetCode1307. 口算难题

给你一个方程,左边用 words 表示,右边用 result 表示。
你需要根据以下规则检查方程是否可解:
每个字符都会被解码成一位数字(0 - 9)。
每对不同的字符必须映射到不同的数字。
每个 words[i] 和 result 都会被解码成一个没有前导零的数字。
左侧数字之和(words)等于右侧数字(result)。
如果方程可解,返回 True,否则返回 False。
示例 1:
输入:words = [“SEND”,“MORE”], result = “MONEY”
输出:true
解释:映射 ‘S’-> 9, ‘E’->5, ‘N’->6, ‘D’->7, ‘M’->1, ‘O’->0, ‘R’->8, ‘Y’->‘2’
所以 “SEND” + “MORE” = “MONEY” , 9567 + 1085 = 10652
示例 2:

输入:words = [“SIX”,“SEVEN”,“SEVEN”], result = “TWENTY”
输出:true
解释:映射 ‘S’-> 6, ‘I’->5, ‘X’->0, ‘E’->8, ‘V’->7, ‘N’->2, ‘T’->1, ‘W’->‘3’, ‘Y’->4
所以 “SIX” + “SEVEN” + “SEVEN” = “TWENTY” , 650 + 68782 + 68782 = 138214
示例 3:

输入:words = [“THIS”,“IS”,“TOO”], result = “FUNNY”
输出:true
示例 4:

输入:words = [“LEET”,“CODE”], result = “POINT”
输出:false

提示:

2 <= words.length <= 5
1 <= words[i].length, results.length <= 7
words[i], result 只含有大写英文字母
表达式中使用的不同字符数最大为 10

回溯

简单的例子
AB + AC = BCD
10A+B+10A+C = 100B+10C+D
20A-99B -9C-D = 0
系数20,-99,-9,-1 放到向量v中,并排序。如果直接回溯,时间复杂度1010超时。
将v排序,从后到前处理。处理v[i],先估算v[0,i)的最小值iMin和最大值iMax,如果已有值x+iMin > 0或 x+iMax < 0,则剪枝忽略。
求最小值:
如果存在负数,最小的负数(绝对值最大)对应最大的未选择值。如果存在正数,最大的正数取最小的未选择数。
求最大值:
如果存在负数,最小的负数(绝对值最大)对应最小的未选择值。如果存在正数,最大的正数取最大的未选择数。

代码

核心代码(超时)

class Solution {
public:bool isSolvable(vector<string>& words, string result) {unordered_map<char, int> mCharCnt;	unordered_map<char, bool> mCharNot0;//开头不能为0auto Add = [&](int iMul, const string& s){for (int i = s.length() - 1; i >= 0; i--, iMul*=10){mCharCnt[s[i]] += iMul;}if (s.length() > 1){mCharNot0[s[0]] = true;}};for (const auto& s : words){Add(1, s);}Add(-1, result);vector<pair<int,int>> v;for (const auto& [tmp, cnt] : mCharCnt){v.emplace_back(cnt,mCharNot0[tmp]);}sort(v.begin(), v.end());set<int> setSel;for (int i = 0; i < 10; i++){setSel.emplace(i);}return DFS(v, setSel, 0, 0);}template<class Pr>int MinMax(const pair<int, int>*p, int n, set<int,Pr> setSel){int result = 0;for (int i = 0; i != n;){if (p[i].first < 0){result += *setSel.begin()*p[i++].first;setSel.erase(setSel.begin());}else{result += *setSel.rbegin()*p[--n].first;setSel.erase(std::prev(setSel.end()));}}return result;}bool DFS(const vector<pair<int,int>> & v, set<int>& setSel, int leve, int result){if (v.size() == leve){return 0 == result;}const int iMin = MinMax(v.data()+leve, v.size()-leve, set<int, std::greater<int>>(setSel.begin(), setSel.end()));const int iMax = MinMax(v.data() + leve, v.size() - leve, setSel);if ((iMin + result > 0) || (iMax + result < 0)){return false;}for (int i = 9; i >= v[leve].second; i--){if (!setSel.count(i)){continue;}setSel.erase(i);			if (DFS(v, setSel, leve + 1, result + v[leve].first * i)){return true;}setSel.emplace(i);}return false;}	
};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{vector<string> words;string result;{Solution sln;words = { "A","B" }, result = "A";auto res = sln.isSolvable(words, result);Assert(true, res);}{Solution sln;words = { "CBA","CBA","CBA","CBA","CBA" }, result = "EDD";auto res = sln.isSolvable(words, result);Assert(false, res);}{Solution sln;words = { "SEND", "MORE" }, result = "MONEY";auto res = sln.isSolvable(words, result);Assert(true, res);}{Solution sln;words = { "SIX", "SEVEN", "SEVEN" }, result = "TWENTY";auto res = sln.isSolvable(words, result);Assert(true, res);}{Solution sln;words = { "THIS", "IS", "TOO" }, result = "FUNNY";auto res = sln.isSolvable(words, result);Assert(true, res);}{Solution sln;words = { "LEET", "CODE" }, result = "POINT";auto res = sln.isSolvable(words, result);Assert(false, res);}
}

估算最小值最大值

pair<int,int> MinMaxSingle(const pair<int, int>* p, int n)
{int less0 = 0, more0 = 0;for (int i = 0; i < n ; i++ ){if (p[i].first < 0){less0 += p[i].first;}else{more0 += p[i].first;}}return { less0 * 9,more0 * 9 };
}

可以提升一倍,还是过不了。
一,for循环也可以省略。
二,向量变原生数组。
这两个方法效果很小。

class Solution {
public:bool isSolvable(vector<string>& words, string result) {unordered_map<char, int> mCharCnt;	unordered_map<char, bool> mCharNot0;//开头不能为0auto Add = [&](int iMul, const string& s){for (int i = s.length() - 1; i >= 0; i--, iMul*=10){mCharCnt[s[i]] += iMul;}if (s.length() > 1){mCharNot0[s[0]] = true;}};for (const auto& s : words){Add(1, s);}Add(-1, result);pair<int, int> v[10];int less0 = 0, more0 = 0;for (const auto& [tmp, cnt] : mCharCnt){v[m_c++] = { cnt,mCharNot0[tmp] };			if (cnt < 0){less0 += cnt;}else{more0 += cnt;}}sort(v, v+m_c);set<int> setSel;for (int i = 0; i < 10; i++){setSel.emplace(i);}return DFS(v, setSel, 0, 0,more0,less0);}bool DFS(const pair<int, int>* p, set<int>& setSel, int leve, int result,int more0,int less0){if (m_c == leve){return 0 == result;}if ((less0*9 + result > 0) || (more0*9 + result < 0)){return false;}for (int i = 9; i >= p[leve].second; i--){if (!setSel.count(i)){continue;}setSel.erase(i);		const int curLess0 = min(0, p[leve].first);const int curMore0 = max(0, p[leve].first);if (DFS(p, setSel, leve + 1, result + p[leve].first * i,more0+curMore0,less0+curLess0)){return true;}setSel.emplace(i);}return false;}	int m_c = 0;
};

先处理绝对值大的

速度提升大约1000倍。

class Solution {
public:bool isSolvable(vector<string>& words, string result) {unordered_map<char, int> mCharCnt;	unordered_map<char, bool> mCharNot0;//开头不能为0auto Add = [&](int iMul, const string& s){for (int i = s.length() - 1; i >= 0; i--, iMul*=10){mCharCnt[s[i]] += iMul;}if (s.length() > 1){mCharNot0[s[0]] = true;}};for (const auto& s : words){Add(1, s);}Add(-1, result);pair<int, int> v[10];int less0 = 0, more0 = 0;for (const auto& [tmp, cnt] : mCharCnt){v[m_c++] = { cnt,mCharNot0[tmp] };			if (cnt < 0){less0 += cnt;}else{more0 += cnt;}}sort(v, v + m_c, [&](const auto& pr1, const auto& pr2) {return abs(pr1.first) > abs(pr2.first); });set<int> setSel;for (int i = 0; i < 10; i++){setSel.emplace(i);}return DFS(v, setSel, 0, 0,more0,less0);}bool DFS(const pair<int, int>* p, set<int>& setSel, int leve, int result,int more0,int less0){if (m_c == leve){return 0 == result;}if ((less0*9 + result > 0) || (more0*9 + result < 0)){return false;}for (int i = 9; i >= p[leve].second; i--){if (!setSel.count(i)){continue;}setSel.erase(i);		const int curLess0 = min(0, p[leve].first);const int curMore0 = max(0, p[leve].first);if (DFS(p, setSel, leve + 1, result + p[leve].first * i,more0-curMore0,less0-curLess0)){return true;}setSel.emplace(i);}return false;}	int m_c = 0;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

2024年云计算使用报告,89%组织用多云,25%广泛使用生成式AI,45%需要跨云数据集成,节省成本是云首要因素

备注&#xff1a;本文来自Flexera2024年的云现状调研报告的翻译。原报告地址&#xff1a; https://info.flexera.com/CM-REPORT-State-of-the-Cloud Flexera是一家专注于做SaaS的IT解决方案公司&#xff0c;有30年发展历史&#xff0c;5万名客户&#xff0c;1300名员工。Flex…

夜莺浏览日志、filebeat采集日志(四)

文章目录 一、elasticsearch二、filebeat三、日志分析 一、elasticsearch docker启动 docker run -d -p 9200:9200 -p 9300:9300 --restartalways -e ES_JAVA_OPTS"-Xms512m -Xmx512m" \ -e discovery.typesingle-node -e xpack.security.enabledtrue -e ELASTIC_P…

使用GO对PostgreSQL进行有意思的多线程压测

前言 针对PostgreSQL进行压缩&#xff0c;有很多相关的工具。有同学又要问了&#xff0c;为何还要再搞一个&#xff1f;比如&#xff0c;pgbench, sysbench之类的&#xff0c;已经很强大了。是的&#xff0c;它们都很强大。但有时候&#xff0c;在一些特殊的场景&#xff0c;可…

Django开发复盘

一、URL 对于一个不会写正则表达式的蒟蒻来说&#xff0c;在urls.py中就只能傻傻的写死名字&#xff0c;但是即便这样&#xff0c;还会有很多相对路径和绝对路径的问题&#xff08;相对ip端口的路径&#xff09;&#xff0c;因为我们网页中涉及到页面跳转&#xff0c;涉及到发送…

Tuxera for Mac2024免费读写硬盘U盘工具

作为软件产品专家&#xff0c;我对各类软件都有较为深入的了解&#xff0c;下面介绍Tuxera for Mac这款读写硬盘/U盘工具的相关信息&#xff1a; Tuxera for Mac是一款高效稳定的NTFS读写工具&#xff0c;专为解决Mac系统无法直接读写NTFS格式驱动器的问题而设计。它提供了完整…

Android 自定义EditText

文章目录 Android 自定义EditText概述源码可清空内容的EditText可显示密码的EditText 使用源码下载 Android 自定义EditText 概述 定义一款可清空内容的 ClearEditText 和可显示密码的 PasswordEditText&#xff0c;支持修改提示图标和大小、背景图片等。 源码 基类&#xf…

实现商铺和缓存与数据库双写一致

2.4 实现商铺和缓存与数据库双写一致 核心思路如下&#xff1a; 修改ShopController中的业务逻辑&#xff0c;满足下面的需求&#xff1a; 根据id查询店铺时&#xff0c;如果缓存未命中&#xff0c;则查询数据库&#xff0c;将数据库结果写入缓存&#xff0c;并设置超时时间…

ssm小区车库停车系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 ssm小区车库停车系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模…

如何在家中使用手机平板电脑 公司iStoreOS软路由实现远程桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…

HCIA-Datacom实验_03_实验一:华为VRP系统基本操作

1.运行eNSP&#xff0c;设置-界面设置-自定义界面-设备标签&#xff0c;“总显示接口标签” 打钩。 2.按照实验拓扑添加设备 注&#xff1a;如果是真实环境&#xff0c;需要接两条线&#xff1a; &#xff08;1&#xff09;串口线&#xff1a;电脑USB口到网络设备Console口&am…

Windows下载使用nc(netcat)命令

‘nc’ 不是内部或外部命令&#xff0c;也不是可运行的程序&#xff1f; 点击链接地址&#xff0c;下载压缩包。 完成后解压 使用方式&#xff08;三种&#xff09;&#xff1a; 1、直接双击exe使用 2、把这个exe放到cmd启动的默认路径下 放到默认路径下&#xff0c;使用nc&a…

MySQL高级语句(二)

一、前期准备工作 1.1 登陆mysql&#xff0c;查看数据表 1.2 显示所有表 1.3 创建guigui表并插入数据 1.4 创建ky35表格并插入数据 二、子连接 子查询也被称作内查询或者嵌套查询&#xff0c;是指在一个查询语句里面还嵌套着另一个查询语句。子查询语句是先于主查询语句被执行的…

自动生成测试位置吸附脚本设计思路

前言 计算一个异质结需要测试对比不同吸附位置之间的能量差异&#xff0c;可以直接手动建模&#xff0c;但是人太懒了&#xff0c;能交给机器的自己就别动手 问题描述 如图上所示是我计算吸附用的衬底&#xff0c;当原子在上面吸附时我考虑了25个&#xff08;可以随便取&…

Tensorflow2.0笔记 - 使用compile,fit,evaluate,predict简化流程

本笔记主要用compile, fit, evalutate和predict来简化整体代码&#xff0c;使用这些高层API可以减少很多重复代码。具体内容请自行百度&#xff0c;本笔记基于FashionMnist的训练笔记&#xff0c;原始笔记如下&#xff1a; Tensorflow2.0笔记 - FashionMnist数据集训练-CSDN博…

OSPF-区域间路由计算

一、概述 前面学习了我们学习了Router-LSA和Network-LSA&#xff0c;它们都只能在区域内进行泛洪&#xff0c;而且我们之前一直主要是单区域学习。OSPF的核心是骨干区域Area 0&#xff0c;其它都为非骨干区域。但是在大型网络中&#xff0c;单区域OSPF会存在一定的问题&#xf…

[BT]BUUCTF刷题第9天(3.27)

第9天&#xff08;共2题&#xff09; [护网杯 2018]easy_tornado 打开网站就是三个txt文件 /flag.txt flag in /fllllllllllllag/welcome.txt render/hints.txt md5(cookie_secretmd5(filename))当点进flag.txt时&#xff0c;url变为 http://b9e52e06-e591-46ad-953e-7e8c5f…

gopher伪协议

基础知识 基本格式 基本格式&#xff1a;URL:gopher://<host>:<port>/<gopher-path>web也需要加端口号80gophert协议默认端口为70gopheri请求不转发第一个字符 get请求 问号&#xff08;&#xff1f;)需要转码为URL编码&#xff0c;也就是%3f回车换行要变…

【Linux】信号的处理{信号处理的时机/了解寄存器/内核态与用户态/信号操作函数}

文章目录 0.对于信号捕捉的理解1.信号处理的时机1.1 何时处理信号&#xff1f;1.2 内核态和用户态1.3 内核态和用户态的切换 2.了解寄存器3.信号捕捉的原理4.信号操作函数4.1sighandler_t signal(int signum, sighandler_t handler);4.2int sigaction(int signum, const struct…

IP如何异地共享文件?

【天联】 组网由于操作简单、跨平台应用、无网络要求、独创的安全加速方案等原因&#xff0c;被几十万用户广泛应用&#xff0c;解决了各行业客户的远程连接需求。采用穿透技术&#xff0c;简单易用&#xff0c;不需要在硬件设备中端口映射即可实现远程访问。 异地共享文件 在…

基于SpringBoot和Vue的校园管理系统的设计与实现

今天要和大家聊的是一款基于SpringBoot和Vue的校园管理系统的设计与实现 &#xff01;&#xff01;&#xff01; 有需要的小伙伴可以通过文章末尾名片咨询我哦&#xff01;&#xff01;&#xff01; &#x1f495;&#x1f495;作者&#xff1a;李同学 &#x1f495;&#x1f…