【回溯 代数系统】679. 24 点游戏

news2025/1/18 10:51:56

本文涉及知识点

回溯 代数系统

LeetCode679. 24 点游戏

给定一个长度为4的整数数组 cards 。你有 4 张卡片,每张卡片上都包含一个范围在 [1,9] 的数字。您应该使用运算符 [‘+’, ‘-’, ‘*’, ‘/’] 和括号 ‘(’ 和 ‘)’ 将这些卡片上的数字排列成数学表达式,以获得值24。
你须遵守以下规则:
除法运算符 ‘/’ 表示实数除法,而不是整数除法。
例如, 4 /(1 - 2 / 3)= 4 /(1 / 3)= 12 。
每个运算都在两个数字之间。特别是,不能使用 “-” 作为一元运算符。
例如,如果 cards =[1,1,1,1] ,则表达式 “-1 -1 -1 -1” 是 不允许 的。
你不能把数字串在一起
例如,如果 cards =[1,2,1,2] ,则表达式 “12 + 12” 无效。
如果可以得到这样的表达式,其计算结果为 24 ,则返回 true ,否则返回 false 。
示例 1:
输入: cards = [4, 1, 8, 7]
输出: true
解释: (8-4) * (7-1) = 24
示例 2:
输入: cards = [1, 2, 1, 2]
输出: false

提示:

cards.length == 4
1 <= cards[i] <= 9

回溯、代数系统:错误

枚举cards的所有排列。每种排列的两张卡牌直接枚举加减乘除。从左向右向右运行,可以理解为加了括号。
比如:c1,c2,c3,c4 ,((c1?c2)?c3)?c4 ?表示运算符。
可以用分数(pair) 组成代数系统,任何结果都可以用a+b*c表示。
初始:{0,1,c1}
加法: {a+b × \times ×c,1,x}
减法:{a+b × \times ×c,-1,x}
乘法:{a,b × \times ×c,x}
除法:{a,b × \times ×c, 1 x \frac {1} {x } x1}

错误原因

6/(1 - 3/4) 无法用代数系统表示

核心代码

class Solution {
public:
	bool judgePoint24(vector<int>& cards) {
		sort(cards.begin(), cards.end());
		do {
			int hasDo = 0;
			std::function<void(pair<int, int>, pair<int, int>, pair<int, int>)> BackTrack = [&](pair<int, int> a, pair<int, int> b, pair<int, int>c )
			{
				if (3 == hasDo) {
					auto res = Cal(a, b, c);
					m_bRes |= Is(res);
					return ;
				}
				auto x = cards[hasDo + 1];
				hasDo++;
				BackTrack(Cal(a, b, c), { 1,1 }, { x,1 });
				BackTrack(Cal(a, b, c), { -1,1 }, { x,1 });
				BackTrack(a, Mul(b,c), { x,1 });
				BackTrack(a, Mul(b, c), { 1,x });
				hasDo--;
			};
			BackTrack({ 0,1 }, { 1,1 }, { cards[0],1 });
		} while (next_permutation(cards.begin(), cards.end()));
		return m_bRes;
	}
	pair<int, int> Mul(const pair<int, int>& a, const pair<int, int>& b) {
		return { a.first * b.first,a.second * b.second };
	}
	pair<int, int> Cal(const pair<int, int>& a, const pair<int, int>& b, const pair<int, int>& c) {
		auto d = Mul(b,c);	
		if ((0 == d.second) || (0 == a.second)) { return { 1,0 }; }
		return {a.first*d.second +d.first*a.second,d.second *a.second};
	}
	bool Is(const pair<int, int>& a) {
		if (0 == a.second) { return false; }
		return a.second * 24 == a.first;
	}
	bool m_bRes = false;
};

回溯

4个任意选两个数,考虑顺序。也就是P 4 2 _4^2 42。枚举4个运算符。4个数变成48种3个数。
从任意三个数中选择2个,由于考虑顺序,有6种可能。枚举4种运算符,也就是24种。
对于任意两个数,考虑顺序,有2个选择可能。枚举4种运算符,也就是8种可能。
总时间复杂度:O(48248) < O(105)

代码

class Solution {
public:
	bool judgePoint24(vector<int>& cards) {
		std::function<void(vector<pair<int, int>>&)> BackTrack = [&](vector<pair<int, int>>& card)
		{
			if (1 == card.size()) {		
				m_bRes |= Is(card[0]);
				return;
			}
			for (int i = 0; i < card.size(); i++) {
				for (int j = 0; j < card.size(); j++) {
					if (i == j) { continue; }
					vector<pair<int, int>> tmp;
					for (int k = 0; k < card.size(); k++) {
						if ((k == i) || (k == j)) { continue; }
						tmp.emplace_back(card[k]);
					}
					tmp.emplace_back(make_pair( 0,0));
					tmp.back() = Mul(card[i], card[j]);
					BackTrack(tmp);
					tmp.back() = Mul(card[i], { card[j].second,card[j].first });
					BackTrack(tmp);
					tmp.back() = Add(card[i], card[j]);
					BackTrack(tmp);
					tmp.back() = Add(card[i], { -card[j].first,card[j].second });
					BackTrack(tmp);
				}
			}
		};
		vector<pair<int, int>> card = { {cards[0],1},{cards[1],1},{cards[2],1},{cards[3],1} };
		BackTrack(card);
		return m_bRes;
	}
	pair<int, int> Mul(const pair<int, int>& a, const pair<int, int>& b) {
		return { a.first * b.first,a.second * b.second };
	}
	pair<int, int> Add(const pair<int, int>& a, const pair<int, int>& b) {
		return { a.first * b.second + b.first * a.second,b.second * a.second };
	}
	bool Is(const pair<int, int>& a) {
		if (0 == a.second) { return false; }
		return a.second * 24 == a.first;
	}
	bool m_bRes = false;
};

2023年5月

struct SDecimal
{
SDecimal(int iNum=0, int iDeno = 1)
{
m_iNum = iNum;
m_iDeno = iDeno;
int iGCD = GCD(abs(m_iNum), abs(m_iDeno));
m_iNum /= iGCD;
m_iDeno /= iGCD;
if (m_iDeno < 0)
{
m_iDeno = -m_iDeno;
m_iNum = -m_iNum;
}
}
SDecimal operator*(const SDecimal& o)const
{
return SDecimal(m_iNumo.m_iNum, m_iDenoo.m_iDeno);
}
SDecimal operator/(const SDecimal& o)const
{
return SDecimal(m_iNumo.m_iDeno, m_iDenoo.m_iNum);
}
SDecimal operator+(const SDecimal& o)const
{
const int iGCD = GCD(m_iDeno, o.m_iDeno);
const int iDeno = m_iDenoo.m_iDeno / iGCD;
return SDecimal(m_iNum
(iDeno / m_iDeno) + o.m_iNum*(iDeno / o.m_iDeno), iDeno);
}
SDecimal operator-(const SDecimal& o)const
{
const int iGCD = GCD(m_iDeno, o.m_iDeno);
const int iDeno = m_iDenoo.m_iDeno / iGCD;
return SDecimal(m_iNum
(iDeno / m_iDeno) - o.m_iNum*(iDeno / o.m_iDeno), iDeno);
}
bool operator==(const SDecimal& o)const
{
return (m_iNum == o.m_iNum) && (m_iDeno == o.m_iDeno);
}
bool operator<(const SDecimal& o)const
{
auto tmp = *this - o;
return tmp.m_iNum < 0;
}
int m_iNum=0;//分子
int m_iDeno=1;//分母
};

class Solution {
public:
bool judgePoint24(vector& cards) {
m_cards = cards;

	vector<int> indexs;
	DFS(indexs);
	return m_bSuc;
}
void DFS(vector<int>& indexs )
{
	if (4 == indexs.size())
	{
		vector<SDecimal> datas;
		for (const auto& index : indexs)
		{
			datas.emplace_back(m_cards[index]);
		}
		DFSCal(datas);
		return;
	}
	for (int i = 0; i < 4; i++)
	{
		if (indexs.end() != std::find(indexs.begin(), indexs.end(), i))
		{
			continue;
		}
		indexs.emplace_back(i);
		DFS(indexs);
		indexs.pop_back();
	}
}
void DFSCal(const vector<SDecimal>& datas)
{
	if ((1 == datas.size()) && (datas[0] == 24 ))
	{
		m_bSuc = true;
		return;
	}
	vector<SDecimal> vRet;
	for (int i = 0; i + 1 < datas.size(); i++)
	{
		vector<SDecimal> vParam;
		for (int j = 0; j < i; j++)
		{
			vParam.emplace_back(datas[j]);
		}
		vParam.emplace_back(0);
		for (int j = i + 2; j < datas.size(); j++)
		{
			vParam.emplace_back(datas[j]);
		}
		vParam[i] = datas[i] * datas[i + 1];
		DFSCal(vParam);
		if (0 != datas[i + 1].m_iNum)
		{
			vParam[i] = datas[i] / datas[i + 1];
			DFSCal(vParam);
		}			
		vParam[i] = datas[i] + datas[i + 1];
		DFSCal(vParam);
		vParam[i] = datas[i] - datas[i + 1];
		DFSCal(vParam);
	}
}
vector<int> m_cards;
bool m_bSuc = false;

};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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.coloradmin.cn/o/1674524.html

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

相关文章

【C#】WPF加载浏览器

结果展示 下载SDK 前端代码 红色框住的为添加代码 <Window x:Class"WPFwebview.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://…

TCP四次挥手——断开连接 滑动窗口-流量控制

四次挥手 在TCP的四次挥手中&#xff0c;其重要作用就是释放客户端和服务器的连接。 这里的一些参数非常重要&#xff0c;因为这些参数的作用是为了表达TCP四次挥手断开连接的过程。 其中的参数如下 1.FIN&#xff1a;FIN (Finish) 是TCP协议中的一个标志位&#xff0c;用于…

推荐网站(9)pixabay免费可商用的图片、视频、插画、矢量图、音乐

今天推荐一款可以免费可商用的图片、视频、插画、矢量图、音乐的资源网站&#xff0c;这里面的所以东西都是免费的&#xff0c;并且可以商用。对那些做视频剪辑的人来说帮助非常大。它里面的资源非常的丰富&#xff0c;质量也高。 比如搜索下雨 链接直达&#xff1a;https://pi…

解决webstorm没有vue语法提示;webstorm没有代码提示

解决webstorm没有vue语法提示&#xff1b;webstorm没有代码提示 使用webstorm 2023.x 开发vue项目。发现死活没有vue语法提示&#xff0c;即便是npm install、清理缓存。对比其他vue项目却有语法提示&#xff0c;最后发现依赖库被忽略了&#xff1a; 删除掉node_modules 的忽略…

huggingface:利用git克隆目标资源

前言 因为有很多模型资源都被放在了huggingface上&#xff0c;为了下载它们&#xff0c;着实让一个不懂git的人犯了难&#xff0c;绕了很多远路&#xff0c;甚至将不需要解决的问题也都拿上了台面&#xff0c;因此我将在本篇博客中记载一些关于【huggingface】中利用git克隆目标…

apisix3.9.1 和 dashboard 离线安装

服务器配置 centos7 linux x86 64 前置 需要将离线安装包上传到服务器上 {上传目录 /root/apisix-soft/ } 【建议:优先上传etcd-*.jar \ apisix-*.rpm \ cyrus-*.rpm \ openldap-*.rpm 等安装好apisix后再上传apisix-dashboard-*.rpm】 可以自行网上寻找&#xff0c;或找一台可…

Python接口自动化测试之动态数据处理

在前面的知识基础上介绍了在接口自动化测试中&#xff0c;如何把数据分离出来&#xff0c;并且找到它的共同点&#xff0c;然后依据这个共同点来找到解决复杂问题的思想。我一直认为&#xff0c;程序是人设计的&#xff0c;它得符合人性&#xff0c;那么自动化测试的&#xff0…

使用命令查看电脑最大支持物理内存容量

一、Windows 系统 以管理员身份运行 cmd C:\WINDOWS\system32>wmic memphysical get maxcapacity /format:value将返回值除以1024&#xff0c;再除以1024&#xff0c;即本机最大支持的内存容量 或一行命令直接获取返回值 for /f "tokens2 delims" %I in (wmic…

怎么给视频加水印?2招轻松搞定

在数字媒体时代&#xff0c;视频水印作为一种有效的版权保护手段&#xff0c;被广泛应用于各种场景。给视频添加水印不仅可以防止内容被恶意盗用&#xff0c;还能增加视频的辨识度&#xff0c;提升品牌形象。本文将为您介绍2种简单易行的方法&#xff0c;教您怎么给视频加水印&…

保研机试之【动态规划】

本文为博客&#xff1a;动态规划解题套路框架 | labuladong 的算法笔记 的笔记 前言 动态规划问题的一般形式就是求最值&#xff0c;求解动态规划的核心问题是穷举。动态规划三要素为&#xff1a;最优子结构、重叠子问题、状态转移方程。首先要判断&#xff0c;该问题是否具有…

模电·场效应管放大电路的动态分析_039

场效应管放大电路的动态分析 一、场效应管的低频小信号等效模型二、基本共源放大电路的动态分析三、基本共漏放大电路的动态分析 一、场效应管的低频小信号等效模型 与分析晶体管的 h h h参数等效模型相同&#xff0c;将场效应管也看成一个两端口网络&#xff0c;栅极与源极之间…

MobileNet 网络详解

一、了解 网络亮点&#xff1a; 1、DW网络&#xff0c;大大减少运算量和参数数量 2、增加超参数&#xff1a;控制卷积层卷积核个数的超参数 &#xff0c;控制图像输入大小的超参数 &#xff0c;这两个超参数是人为设定的&#xff0c;不是机器学习到的。 二、DW卷积&#xff…

怎么防止源代码防泄密

随着数字化时代的到来&#xff0c;源代码作为企业和个人的重要资产之一&#xff0c;承载着无价的知识和创新。然而&#xff0c;源代码泄露已成为当今信息安全领域的重要挑战之一&#xff0c;给企业带来了严重的经济损失和声誉风险。面对这一挑战&#xff0c;我们有责任加强对源…

亿级流量系统架构设计与实战

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

【火热征稿~~】2024年心理、哲学与历史国际会议(ICPPH 2024)

2024年心理、哲学与历史国际会议&#xff08;ICPPH 2024&#xff09; 2024 International Conference on Psychology, Philosophy, and History 【会议简介】 2024年心理、哲学与历史国际会议将于历史文化名城武汉召开。此次盛会集结了来自世界各地的心理学家、哲学家和历史学…

01软件下载安装和P解

凯哥英语视频 软件下载安装和P解 凯哥英语视频1.官网直接下&#xff0c;专业版安装不会有人不会吧实在下载不到就去我这百度云吧结语 1.官网直接下&#xff0c;专业版 点击前往逛网下载https://www.jetbrains.com/pycharm/ 下载专业版&#xff0c;奶茶外卖都能点&#xff0c;只…

【爬虫】爬取股票数据写入数据库并显示(四)

本文所涉及代码已全部打包上传&#xff0c;需要可以到文章末尾查看获取方式&#xff0c;免费&#xff0c;仅做学习交流&#xff01;&#xff01;&#xff01; 股票客户端软件 2024/05&#xff0c;本文主要内容如下&#xff1a; 使用python requests爬取东方财富官网数据。将爬…

ros1版本apollo感知融合算法

apollo.ros-7.0.0 本文章针对apollo 7.0.0版本进行了ros1移植&#xff0c;具体介绍见下文。 PS&#xff1a;项目开发详细了解可在评论区留言。 ros版本apollo7.0.0感知算法 基于ros1的apollo 7.0.0感知融合算法。 简介 此项目基于ros1的apollo 7.0.0感知融合算法&#xff0…

05. 【Java教程】第一个 Java 程序

本节我们将以Windows操作系统为例&#xff0c;编写并执行第一个Java程序。在这之前&#xff0c;请确保你的操作系统上已经安装了JDK 1. 编译程序 大家可能有个疑问&#xff0c;为什么需要编译程序呢&#xff1f;计算机不能直接执行我们编写的源代码吗&#xff1f; 这是由于计…

OV SSL证书的特点

OV SSL证书&#xff0c;全称为Organization Validation SSL Certificate&#xff08;组织验证型SSL证书&#xff09;&#xff0c;是一种中级的SSL证书类型。与仅验证域名所有权的DV&#xff08;Domain Validation&#xff09;证书不同&#xff0c;OV证书在颁发前会执行更加严格…