【性能优化】 【回溯】 【字符串】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.mzph.cn/news/775586.shtml

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

相关文章

云原生(六)、CICD - Jenkins快速入门

Jenkuns快速入门 一、CICD概述 CICD是持续集成&#xff08;Continuous Integration&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;的缩写。它是软件开发中的一种流程和方法论&#xff0c;旨在通过自动化的方式频繁地将代码集成到共享存储库中&#xf…

策略路由-IP-Link-路由协议简介

策略路由 策略路由和路由策略的不同 1.策略路由的操作对象是数据包&#xff0c;在路由表已经产生的情况下&#xff0c;不按照路由表进行转发&#xff0c;而是根据需要&#xff0c;依照某种策略改变数据包的转发路径 2.路由策略的操作对象是路由信息。路由策略的主要实现了路…

nginx代理服务后,有关文件的操作无法执行,nginx代理jupyter或为知笔记后无法创建文件及文件夹,无法操作文件

nginx配置 server {listen 18001; # 修改转发的接口listen [::]:18001; # 修改转发的接口server_name _;root /usr/share/nginx/html;location / {proxy_pass http://127.0.0.1:7777; # 指定自己服务地址proxy_set_header Host $host;}# Load configurat…

服务器监控软件夜莺采集监控(三)

文章目录 一、采集器插件1. exec插件2. rabbitmq插件3. elasticsearch插件 二、监控仪表盘1. 系统信息2. 数据服务3. NginxMQ4. Docker5. 业务日志 一、采集器插件 1. exec插件 input.exec/exec.toml [[instances]] commands ["/home/monitor/categraf/scripts/*.sh&q…

【深度学习】图片预处理,分辨出模糊图片

ref:https://pyimagesearch.com/2015/09/07/blur-detection-with-opencv/ 论文 ref:https://www.cse.cuhk.edu.hk/leojia/all_final_papers/blur_detect_cvpr08.pdf 遇到模糊的图片&#xff0c;还要处理一下&#xff0c;把它挑出来&#xff0c;要么修复&#xff0c;要么弃用。否…

信号处理--情绪分类数据集DEAP预处理(python版)

关于 DEAP数据集是一个常用的情绪分类公共数据&#xff0c;在日常研究中经常被使用到。如何合理地预处理DEAP数据集&#xff0c;对于后端任务的成功与否&#xff0c;非常重要。本文主要介绍DEAP数据集的预处理流程。 工具 图片来源&#xff1a;DEAP: A Dataset for Emotion A…

【深度学习】深度学习md笔记总结第2篇:TensorFlow介绍,学习目标【附代码文档】

深度学习笔记完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;深度学习课程&#xff0c;深度学习介绍要求,目标,学习目标,1.1.1 区别,学习目标,学习目标。TensorFlow介绍&#xff0c;2.4 张量学习目标,2.4.1 张量(Tensor),2.4.2 创建张量的指令,2.4.3 张量…

02.percona Toolkit工具pt-archiver命令实践

1.命令作用 Percona Toolkit有的32个命令&#xff0c;可以分为7大类 工具类别 工具命令 工具作用 备注 开发类 pt-duplicate-key-checker 列出并删除重复的索引和外键 pt-online-schema-change 在线修改表结构 pt-query-advisor 分析查询语句&#xff0c;并给出建议&#x…

Lua热更新(xlua)

发现错误时检查是否:冒号调用 只需要导入asset文件夹下的Plugins和Xlua这两个文件即可,别的不用导入 生成代码 和清空代码 C#调用lua using Xlua; 需要引入命名空间 解析器里面执行lua语法 lua解析器 LuaEnv 单引号是为了避免引号冲突 第二个参数是报错时显示什么提示…

【Java程序设计】【C00389】基于(JavaWeb)Springboot的校园疫情防控系统(有论文)

基于&#xff08;JavaWeb&#xff09;Springboot的校园疫情防控系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过…

H5小程序视频方案解决方案,实现轻量化视频制作

对于许多企业而言&#xff0c;制作高质量的视频仍然是一个技术门槛高、成本高昂的挑战。针对这一痛点&#xff0c;美摄科技凭借其深厚的技术积累和创新能力&#xff0c;推出了面向企业的H5/小程序视频方案解决方案&#xff0c;为企业提供了一种轻量化、高效、便捷的视频制作方式…

蓝桥杯基础练习汇总详细解析(三)——字母图形、01字符串、闰年判断(详细解题思路、代码实现、Python)

试题 基础练习 字母图形 提交此题 评测记录 资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 利用字母可以组成一些美丽的图形&#xff0c;下面给出了一个例子&#…

2024年腾讯云4核8G服务器多少钱一年?买1年送3个月

2024年腾讯云4核8G服务器租用优惠价格&#xff1a;轻量应用服务器4核8G12M带宽646元15个月&#xff0c;CVM云服务器S5实例优惠价格1437.24元买一年送3个月&#xff0c;腾讯云4核8G服务器活动页面 txybk.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云4核8G服务器优惠价格 轻…

软件部署资源计算工具:精确评估资源需求

软件部署资源计算工具&#xff1a;精确评估资源需求 在当今快速发展的信息技术时代&#xff0c;软件部署已成为企业运营不可或缺的一部分。然而&#xff0c;一个常见的挑战是如何精确评估软件部署所需的资源。资源评估不仅关系到软件的性能和稳定性&#xff0c;还直接影响到成…

Ps:通道混合器(工作原理篇)

通过通道混合器 Channel Mixer命令&#xff0c;可以创建高品质的灰度图像、棕褐色图像或其他色调图像&#xff0c;也可以对图像进行创造性的颜色调整&#xff0c;还常用于偏色校正。 要掌握通道混合器的使用方法&#xff0c;需先了解一些基础概念和方法。 1、原色通道 在不同的…

让手机平板成为AI开发利器:AidLux

想ssh登录自己的手机吗&#xff1f; 想在手机上自由的安装lynx、python、vscode、jupyter甚至飞桨PaddlePaddle、Tensorflow、Pytorch和昇思Mindspore吗&#xff1f; 那么看这里....装上AidLux&#xff0c;以上全都有&#xff01; AidLux是一个综合的AI开发平台&#xff0c;…

Vue 与 React:前端框架对比分析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Chrome之解决:插件不能使用问题(十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

深入理解与实践AB测试:从理论到实战案例解析

一、引言 在互联网产品优化和运营策略制定中&#xff0c;AB测试&#xff08;也称为分组测试或随机化对照实验&#xff09;是一种科学且严谨的方法。它通过将用户群体随机分配至不同的实验组&#xff08;通常是A组和B组&#xff09;&#xff0c;对比不同版本的产品或策略对关键…

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

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