文章目录

  • 题目
  • 思路
  • 解法一
  • 解法二
  • 解法三

题目

给你一个方程,左边用 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

思路

如果将字符当作一个变量,整个算式就相当于一个多元一次方程,题目就可以看做是,求解10以内整数的多元一次方程,那么求解步骤就分为两步:

  1. 将字符串整理为多元一次方程,即把字符本身当作变量,而字符所在位置的10进制和当作参数
  2. 求解多元一次方程,这个地方就需要想办法减少计算了,下面给了三个解法,用于求解多元一次方程。

解法一

这个是我第一次的写法,仅通过少量的测试用例,未通过的测试用例是因为超时了,后面通过解法2和解法3分别对其算法和数据结构做了优化,超时测试用例及实现源码如下:

[“LEET”,“CODE”]
“POINT”

public class Solution {Dictionary<char, int> sList = new Dictionary<char, int>();Dictionary<char, int> rList = new Dictionary<char, int>();Dictionary<char, int> kList = new Dictionary<char, int>();bool[] used = new bool[10];char[] kArray;public bool IsSolvable(string[] words, string result){for (int i = 0; i < 10; i++){used[i] = false;}//整理为多元一次方程for (int i = 0; i < words.Length; i++){getFunction(words[i], sList);}getFunction(result, rList);//获取变量总数getKeys(kList, sList);getKeys(kList, rList);kArray = kList.Keys.ToArray<char>();//求解方程return this.findSolution(0);}public void getFunction(string str, Dictionary<char, int> chList){//计算多元一次方程的常量int tmpIdx = 1;for (int j = str.Length - 1; j >= 0; j--){if (chList.ContainsKey(str[j])){chList[str[j]] += tmpIdx;}else{chList[str[j]] = tmpIdx;}tmpIdx *= 10;}}public void getKeys(Dictionary<char, int> kList, Dictionary<char, int> sList){//获取多元变量本身foreach (char k in sList.Keys){if (!kList.ContainsKey(k)){kList.Add(k, 0);}}}public bool checkEqual(Dictionary<char, int> kList){//判断方程两边是否相等int sInt = 0, rInt = 0;foreach (char c in sList.Keys){sInt += sList[c] * kList[c];}foreach (char c in rList.Keys){rInt += rList[c] * kList[c];}return rInt == sInt;}public bool findSolution(int idx){//实际求解if (idx == kArray.Length)return checkEqual(kList);for (int j = 0; j <= 9; j++){if (!used[j]){kList[kArray[idx]] = j;used[j] = true;if (findSolution(idx+1))return true;used[j] = false;}}return false;}
}

解法二

当前解法基于上面的第一种解法做了下面3个角度的优化,来减少运算内容,从而减少时间复杂度。不过,这个解法通过了大部分测试用例,但提交还是提示超时,但单独执行超时的最后一个测试用例显示150ms,可能还有个全部测试用例的整体执行时间约束:

  1. 直接将等式两边值都合并到左边,只是等式右边符号设为负数,减少了查看变量个数的步骤(getKeys函数);
  2. 求解过程的判断直接求和,判断整体是否为0,不需要再进行对比计算(checkEqual函数);
  3. 不需要先记录下来每个变量是多少,然后再进行计算,而是在查询的时候直接计算(kList[kArray[idx]] = j;语句)

[“YOUVE”,“NEVER”,“BEEN”,“TO”]
“EUROPE”

public class Solution {Dictionary<char, int> sList = new Dictionary<char, int>();bool[] used = new bool[10];char[] kArray;public bool IsSolvable(string[] words, string result){for (int i = 0; i < 10; i++){used[i] = false;}//整理为多元一次方程for (int i = 0; i < words.Length; i++){getFunction(words[i], sList,1);}getFunction(result, sList, -1);//获取变量总数kArray = sList.Keys.ToArray<char>();//求解方程return this.findSolution(0,0);}public void getFunction(string str, Dictionary<char, int> chList, int dir){//计算多元一次方程的常量int tmpIdx = 1;for (int j = str.Length - 1; j >= 0; j--){if (chList.ContainsKey(str[j])){chList[str[j]] += tmpIdx * dir;}else{chList[str[j]] = tmpIdx * dir;}tmpIdx *= 10;}}public bool findSolution(int idx,int sum){//实际求解if (idx == kArray.Length)return sum == 0;for (int j = 0; j <= 9; j++){if (!used[j]){used[j] = true;if (findSolution(idx + 1, sum + j * sList[kArray[idx]]))return true;used[j] = false;}}return false;}
}

解法三

基于第二个解法,做了一个优化,将字典用数组替换掉,由于方案本身并不关心具体某个字母是由哪个数值来代表,只要分别为不同的字母使用不同的数组索引即可,这样做减少的步骤是,将通过字典查找值的方式,使用数组索引代替,源码如下:

public class Solution {public bool IsSolvable(string[] words, string result){bool[] used = new bool[10];Dictionary<char, int> sList = new Dictionary<char, int>();for (int i = 0; i < 10; i++){used[i] = false;}//整理为多元一次方程for (int i = 0; i < words.Length; i++){getFunction(words[i], sList,1);}getFunction(result, sList, -1);//获取变量总数int[]vArray = sList.Values.ToArray<int>();//求解方程return this.findSolution(0, 0, vArray,used);}public void getFunction(string str, Dictionary<char, int> chList, int dir){//计算多元一次方程的常量int tmpIdx = 1;for (int j = str.Length - 1; j >= 0; j--){if (chList.ContainsKey(str[j])){chList[str[j]] += tmpIdx * dir;}else{chList[str[j]] = tmpIdx * dir;}tmpIdx *= 10;}}public bool findSolution(int idx, int sum, int[] vArray, bool[] used){//实际求解if (idx == vArray.Length)return sum == 0;for (int j = 0; j <= 9; j++){if (!used[j]){used[j] = true;if (findSolution(idx + 1, sum + j * vArray[idx],vArray,used))return true;used[j] = false;}}return false;}
}

原文地址:https://www.zhenxiangsimple.com/2019/12/30/tech/math-stringCalc/

3个算法 - 口算难题相关推荐

  1. 生成小学加减口算题JAVA算法

    生成小学加减口算题JAVA算法 package com.jianchi.fsp.generationchildrenarithmetic;import java.io.Serializable; im ...

  2. 特殊多位数乘法口算算法

    本文转自:我爱口算网,但是本人有一定更正,因此转载请注明出处 一.关于9的数学口算技巧(两位数乘法) 关于9的口诀: 1 × 9 = 9    2 × 9 = 18   3 × 9 = 27      ...

  3. 口算练习题(模拟算法)

    题目描述 王老师正在教简单算术运算.细心的王老师收集了i道学生经常做错的口算题,并且想整理编写成一份练习. 编排这些题目是一件繁琐的事情,为此他想用计算机程序来提高工作效率.王老师希望尽量减少输入的工 ...

  4. 《口算大作战 2》DLC:算法真奇妙

    211614331 王诚荣 211614354 陈斌 --第一次结对作业 DLC DLC:三年级混合运算模块现已更新!现在您可以愉快的使用三年级题库啦.同时您必须拥有本体才能使用此DLC 单击此处查看 ...

  5. 高中数学,向量高考真题解题技巧(快速口算)

    作者:vxbomath 同学们今天跟大家分享一下向量难得解题技巧,我们平时遇到向量问题的高考真题的时候,常规运算3到5分钟未必得到答案的.我们如何快速的出答案了,老师今天就给大家分享一终思维方式,同学 ...

  6. 50道100以内的加减法口算习题及它的模块化改造

    50道100以内的加减法口算习题及它的模块化改造 目录 50道100以内的加减法口算习题及它的模块化改造 前言 一.未经过模块化设计的基础代码 1.代码示例 2.存在的问题 二.分解与模块化 1.分解 ...

  7. 基于Python和Java混合编程实现的小学生数学口算题卡定制练习题

    1. 总体要求 综合运用软件工程的思想,协同完成一个软件项目的开发,掌软件工程相关的技术和方法: 组成小组进行选题,通过调研完成项目的需求分析,并详细说明小组成员的分工.项目的时间管理等方面. 根据需 ...

  8. 【杂记】从孩子口算题开始逐渐离谱

    文章目录 一. 背景 二.初步实现 main.cpp creater.h creater.cpp 三.优化 修改内容: creater.h creater.cpp 四.复杂化 main.cpp cre ...

  9. 阶段综合应用—口算测试APP

    口算测试app 主要涉及知识点: ·dataBinding的使用 ·ViewModel的使用 ·Fragment的创建 ·代码逻辑 ·本地化 ·横屏适配 需求说明: ·实现20以内随机数的加减法运算 ...

最新文章

  1. How to enable coredump on centos 7.6
  2. springboot扫描组件_SpringBoot入口类和@SpringBootApplication详解
  3. JavaScript中循环遍历JSON响应!
  4. javascript --- 几个其他的跨域技术(图像Ping、JSONP、Comet)
  5. C#与VB.NET代码互相转换在线工具
  6. 照顾好自己才能照顾好别人_您必须照顾的5个基本数据
  7. 桶排序/Bucket Sort
  8. python @classmethod和@staticmethod的区别
  9. 基于Redis的三种分布式爬虫策略
  10. MongoDb 聚合报错
  11. 低代码快速实现跟进提醒
  12. ir2104s的自举电容_有关IR2104的自举电容和NMOS选择问题要点.docx
  13. 打地鼠程序设计c语言,打地鼠游戏的制作(C语言)含代码.ppt
  14. 8.2.1 消息通知过时写法解决
  15. Pytorch—模型微调(fine-tune)
  16. JavaScript世界时万年历
  17. FXGL JAVA游戏引擎 教程 .04 动画 (可爱乌贼娘)
  18. Centos6.8下安装Mysql5.6.14,连接mysql及增删改查,通过Mysql-Front远程连接(开启端口、允许远程连接)
  19. 实战 | OpenCV如何将不同轮廓合并成一个轮廓(附Python / C++源码)
  20. [ABAP] VL09交货单过账冲销BAPI:WS_REVERSE_GOODS_ISSUE的BUG解决

热门文章

  1. 2005年日语词典软件评价加强版
  2. 一段经典的英文爱情对白
  3. 网站怎么接入高防服务器,[网站防护步骤 1] HTTP网站接入/接入网站
  4. 婚礼上新郎经典发言稿
  5. 关于印象笔记的扫描宝——简单的图像背景去除(去底色)算法小结
  6. css多个伪元素,使用CSS伪元素控制连续几个元素的样式方法
  7. HMM经典介绍论文【Rabiner 1989】翻译(三)——抛硬币实验和碗中的球实验
  8. Java中如何正确进行浮点数运算
  9. GDKOI2016 爆零记
  10. markdown写法-删除线、强调