庞果英雄会——最小操作数

解决 PyInstaller 与 `pathlib` 包不兼容的问题 为了避免 PyInstaller 和pathlib包的兼容性问题,最简单的解决办法就是卸载不必要的pathlib包。只需在命令行中运行卸载命令,然后重新打包即可。 阅读详情

题目

给了A、B两个单词和一个单词集合Dict,每个的长度都相同。我们希望通过若干次操作把单词A变成单词B,每次操作可以改变单词中的一个字母,同时,新产生的单词必须是在给定的单词集合Dict中。求所有行得通步数最少的修改方法。

   举个例子如下:

Given:

   A = "hit"

   B = "cog"

   Dict = ["hot","dot","dog","lot","log"]

Return

 [

   ["hit","hot","dot","dog","cog"],

   ["hit","hot","lot","log","cog"]

 ]

    即把字符串A = "hit"转变成字符串B = "cog",有以下两种可能:

  1. "hit" -> "hot" ->  "dot" ->  "dog" -> "cog";
  2. "hit" ->  "hot" ->  "lot" ->  "log"  ->"cog"。

程序分析

利用二叉链表表示法将各字符串按照相差字符个数组织起来,叶子结点是目标串,建立二叉链表时记录从根结点到叶子结点的最小跳数,如果在建立过程中超个过最小跳数,则终止这条路径。

建立完二叉链表后,深度优先遍历记录节点数即可。

结构图:


黄色线表示结点的父亲结点。


测试例子中的树形图为:


黑色虚线表示这条路径的长度超过了最短的路径,只自动丢弃即可,如图从hit-->cog最长为5跳,则hit->hot->dot->lot->log...超过了5跳了,弃之

代码:

#include <string>
#include <vector>
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

typedef struct __Tree
{
	string str;
	struct __Tree *parent;
	struct __Tree *sibling;
	struct __Tree *child;
}Tree;


class Solution
{
private:
	string *m_str;
	Tree m_head;
	int m_n;
public:
	bool compareStr(string &s1, string &s2)
	{
		int count = 0;
		int l = s1.length();
		for(int i = 0; i < l; i++)
		{
			if(s1[i] != s2[i])
			{
				count++;
				if(count > 1)
				{
					break;
				}
			}
		}

		return (count == 1) ? true : false;
	}

	void createTree(string &start, string &end, set<string>& dict)
	{
		set<string>::iterator iter;
		string str;
		bool flag = false;
		Tree *p;

		m_head.str = start;
		m_head.parent = NULL;
		m_head.sibling = NULL;
		m_n = 100000;

		//孩子节点生成过程
		for(iter = dict.begin(); iter != dict.end(); iter++)
		{
			str = *iter;
			if(compareStr(str, m_head.str))//与当前节点比较
			{			
				p = new Tree;
				p->str = str;
				p->parent = &m_head;
				m_head.child = p;
				createNode(*p, 2, end, dict);
				break;
			}
		}

		if(iter == dict.end())//如果没有差一个字符的,判断是否与end一样
		{
			if(compareStr(end, m_head.str))
			{
				p = new Tree;
				p->str = end;
				p->parent = &m_head;
				p->sibling = NULL;//不用向下比较了,之后的一定比当前的长
				m_head.child = p;

				m_n = 2;//记录最小长度
			}
			else
			{
				m_head.child = NULL;
			}
		}
	}

	void createNode(Tree &node, int n, string &end, set<string>& dict)
	{
		set<string>::iterator iter;
		string str;
		bool flag = false;
		Tree *p;

		node.child = NULL;
		node.sibling = NULL;

		//剪枝,大小最小长度,去除
		if(n > m_n)
		{
			return;
		}

		if(compareStr(end, node.str))
		{
			p = new Tree;
			p->str = end;//表示结束
			p->parent = &node;
			p->sibling = NULL;//不用向下比较了,之后的一定比当前的长
			p->child = NULL;
			node.child = p;

			if(n < m_n)
			{
				m_n = n;//记录最小长度
			}
//			return;
		}
		else
		{
			//孩子节点生成过程
			for(iter = dict.begin(); iter != dict.end(); iter++)
			{
				str = *iter;
				if(compareStr(str, node.str))//与当前节点比较
				{
					//兄弟节点比较,找到还没有用过的
					p = node.parent->child;
					while(p)
					{
						if(str.compare(p->str) == 0)
						{
							flag = true;
							break;
						}
						p = p->sibling;
					}
					if(flag == true)
					{
						flag = false;
						continue;
					}

					//父亲节点比较
					p = node.parent;
					while(p)
					{
						if(iter->compare(p->str) == 0)
						{
							flag = true;//节点之前已经存在
							break;
						}
						p = p->parent;
					}

					if(flag == true)
					{
						flag = false;
						continue;
					}

					p = new Tree;
					p->str = str;
					p->parent = &node;
					node.child = p;
					createNode(*p, n + 1, end, dict);
					break;
				}
			}

			if(iter == dict.end())//如果没有符合条件的,置空
			{
				node.child = NULL;
			}
		}

		//兄弟节点生成过程
		flag = false;
		for(iter = dict.begin(); iter != dict.end(); iter++)
		{
			str = *iter;
			if(compareStr(str, node.parent->str))//与父亲节点比较,且与当前节点不同的节点
			{
				//兄弟节点比较,找到还没有用过的
				p = node.parent->child;
				while(p)
				{
					if(str.compare(p->str) == 0)
					{
						flag = true;
						break;
					}
					p = p->sibling;
				}
				if(flag == true)
				{
					flag = false;
					continue;
				}

				//父亲节点比较,找到还没有用过的
				p = node.parent->parent;
				while(p)
				{
					if(iter->compare(p->str) == 0)
					{
						flag = true;//节点之前已经存在
						break;
					}
					p = p->parent;
				}

				if(flag == true)
				{
					flag = false;
					continue;
				}
				
				p = new Tree;
				p->str = str;
				p->parent = node.parent;
				node.sibling = p;
				createNode(*p, n, end, dict);
				break;
			}
		}

		if(iter == dict.end())//如果没有符合条件的,置空
		{
			node.sibling = NULL;
		}
	}

	void DFS(Tree *root, int n, vector<string> &vec, vector<vector<string>> &vvec, string &end)
	{
		vector<string> *p;
		if(root == NULL)
		{
			return;
		}

		if(n > m_n)//超过最小长度的,去除掉
		{
			return;
		}

		cout << "第" << n + 1 << "层:" << root->str<<endl;
		vec.insert(vec.begin() + n, root->str);

		if(root->str.compare(end) == 0)
		{
			p = new vector<string>;
			for(vector<string>::iterator iter = vec.begin(); iter < vec.end(); iter++)
			{
				p->push_back(*iter);
			}
			vvec.push_back(*p);
		}

		DFS(root->child, n + 1, vec, vvec, end);
		
		//去除前一个过程中的后面部分
		for(int i = vec.size(); i > n; i--)
		{
			vec.pop_back();
		}

		DFS(root->sibling, n, vec, vvec, end);


	}

    vector<vector<string>> findLadders(string start, string end, set<string>& dict)
    {
		vector<string> vec;
		vector<vector<string>> vvec;

		if(start == end)
		{
			return vvec;
		}
		else if(compareStr(start, end))
		{
			vec.push_back(start);
			vec.push_back(end);
			vvec.push_back(vec);
		}
		else
		{
			createTree(start, end, dict);
			DFS(&m_head, 0, vec, vvec, end);
		}

		return vvec;
    }
};

测试

测试一:
int main()
{
	Solution aa;
//	string start("a2b");
	string start("hit");
	vector<vector<string>> vec;
	vector<string>a;
//	string end("bmn");
	string end("cog");

	set<string> set1;
	set1.insert("hot");
	set1.insert("dot");
	set1.insert("dog");
	set1.insert("lot");
	set1.insert("log");
	//set1.insert("amn");
	//set1.insert("a2n");
	//set1.insert("b2b");
	//set1.insert("bhb");
	//set1.insert("b2n");
	//set1.insert("ahn");
	vec = aa.findLadders(start, end, set1);

	for(vector<vector<string>>::iterator vviter = vec.begin(); vviter < vec.end(); vviter++)
	{
		cout << *vviter->begin();
		for(vector<string>::iterator iter = vviter->begin() + 1; iter < vviter->end(); iter++)
		{
			cout << "->" <<*iter;
		}
		cout << endl;
	}
	return 0;
}
结果:


测试二:
int main()
{
	Solution aa;
	string start("a2b");
//	string start("hit");
	vector<vector<string>> vec;
	vector<string>a;
	string end("bmn");
//	string end("cog");

	set<string> set1;
	//set1.insert("hot");
	//set1.insert("dot");
	//set1.insert("dog");
	//set1.insert("lot");
	//set1.insert("log");
	set1.insert("amn");
	set1.insert("a2n");
	set1.insert("b2b");
	set1.insert("bhb");
	set1.insert("b2n");
	set1.insert("ahn");
	vec = aa.findLadders(start, end, set1);

	for(vector<vector<string>>::iterator vviter = vec.begin(); vviter < vec.end(); vviter++)
	{
		cout << *vviter->begin();
		for(vector<string>::iterator iter = vviter->begin() + 1; iter < vviter->end(); iter++)
		{
			cout << "->" <<*iter;
		}
		cout << endl;
	}
	return 0;
}
结果:


写在最后:之前自己测试了很多例子,结果都正确,然后就写博客没有提交。但看到大家评论后我也提交了代码,但没有通过,想不到什么原因,可能是溢出或超时。


瑞芯微RV1126部署YOLOv8全流程:环境搭建、pt-onnx-rknn模型转换、C++推理代码、错误解决、优化、交叉编译第三方库 阅读详情

相关推荐

tewa-707e光猫超级密码获取方法

这款光猫很魔性,没有WIFI,没有USB接口,没有Telnet,试了很多方法去获取超级密码都不行。解密时可能会报错,可能是文件后面部分不晓得是咋拼接过来的,用AES解密时分组数据有问题。3、这个文件是用AES加密了的,直接打开是乱码,所以得用AES解密,key为16个字节的 x00。打开解出来的文件,然后搜索 telecomadmin,就可以发现超级密码了。参考资料里面的光猫不是同一款,但解密的方法基本相同的。

shaowl111的专栏 1万+

【庞果英雄会】最小操作数

给了A、B两个单词和一个单词集合Dict,每个的长度都相同。我们希望通过若干次操作把单词A变成单词B,每次操作可以改变单词中的一个字母,同时,新产生的单词必须是在给定的单词集合Dict中。求所有行得通步数最少的修改方法。     举个例子如下:  Given:    A = "hit"    B = "cog"     Dict = ["hot","dot","dog","lot","log

超然于物外 烟火于一瞬 2940

ROS2仿真抓取分拣案例,使用myCobot 280机械臂结合ROS2系统搭建机械分拣站

本案例展示了如何利用myCobot 280 urdf模型构建一个对象分类站,并在ROS2 jazzy中完成运动规划。

m0_71627844的博客 2126

最小操作数(改版)

题目详情: 给了A、B两个单词和一个单词集合Dict,每个的长度都相同。我们希望通过若干次操作把单词A变成单词B,每次操作可以改变单词中的一个字母,同时,新产生的单词必须是在给定的单词集合Dict中。求所有行得通步数最少的修改方法。    举个例子如下: Given:    A = "hit"    B = "cog"    Dict = ["h

liuhuiyi的专栏 1284

Ghost备份还原Win10全攻略:从老电脑迁移到新硬盘,ESP分区处理是关键

本文详细介绍了使用Ghost工具将Win10系统从旧电脑迁移到新硬盘的全过程,特别强调了ESP分区的关键处理方法。通过分步指导备份、分区准备、系统还原和引导修复,帮助用户实现无缝系统迁移,解决常见问题如启动失败和驱动兼容性。

weixin_30823001的博客 672

Cherry Studio部署MCP服务报错全记录:从零解决‘Connection closed‘问题

本文详细记录了在Cherry Studio中部署MCP服务时遇到‘Connection closed’报错的完整排查与解决过程。文章从环境依赖(UV、Bun)的安装验证、绝对路径配置、网络镜像源设置,到服务端手动调试与Cherry Studio配置检查,提供了一套系统性的解决方案,帮助开发者彻底解决此类连接问题。

g9h0i1的博客 765

挑战庞果英雄会之最小操作数(失败求指教)

题目详情   给定两个字符串,仅由小写字母组成,它们包含了相同字符。 求把第一个字符串变成第二个字符串的最小操作次数,且每次操作只能对第一个字符串中的某个字符移动到此字符串中的开头。 例如给定两个字符串“abcd" "bcad" ,输出:2,因为需要操作2次才能把"abcd"变成“bcad" ,方法是:abcd->cabd->bcad。 要将第一个字符串a(abcd)转换为

TheDeaf的专栏 845

深度学习模型设计的方法和技巧

设计神经网络模型是一个迭代的过程,需要不断试验和调整各个组成部分,以达到最佳性能。同时,遵循良好的工程实践,如模块化设计、版本控制、文档记录等,也是成功的关键。

xw555666的博客 4027

庞果网(最小操作数)

从庞果网上,看到一题,是求最小操作数的,具体题目如下: 现用python代码实现如下: 1 #!usr/bin/env python 2 #coding:utf-8 3 4 def compareWord(A,B): 5 wordLen = len(A) 6 diff = 0 7 for i in range(...

207

《UDS协议从入门到精通》系列——图解0x34:请求下载

上传下载类服务之0x34-请求下载,图解请求+响应格式,直观易懂,快速上手!!

车载系统攻城狮 4931

YOLOv11改进策略【模型轻量化】| 替换华为的极简主义骨干网络:VanillaNet

本文记录的是基于VanillaNet的YOLOv11轻量化改进方法研究。VanillaNet的极简主义在于无 shortcut 连接,并且在网络的每个阶段仅使用一层卷积,无额外复杂模块,仅通过自身简洁的架构设计和训练策略,实现有效地训练和优化。本文在替换骨干网络中配置了原论文中的、和11种模型,以满足不同的需求。

Limiiiing的博客 1726

庞果英雄会——数组排序

前些天在pango英雄会上看到了很多编程题,有些跃跃欲试,感觉好久没有做这样的题了,但是又感觉自己的水平有限,所以就选了一个2星/5星的题,试试深浅……题目简单,就当大家一起学习了,希望大神不要嘲笑。 下面是这个题目的描述: 题目详情:数组排序 给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序。求最少需要多少次交换,能把数组排成按1-n递增的顺序,其中,数

u012771929的专栏 729

2024美团秋招硬件开发笔试真题及答案解析

在 Linux 内核的网络设备驱动中,数据链路层的功能通常由网络协议栈的低层(如以太网驱动)实现,而不是作为网络设备驱动的一个独立层次。在 FreeRTOS 中,任务通知(Task Notifications)是一种轻量级的事件传递机制,用于在任务之间或任务与中断之间传递信号。小美正在开发一个简单的密码生成器,其中一个功能是将输入的字符串中的所有字母按字母顺序循环前移一位(即 'a' 变为 'z','B' 变为 'A',以此类推)。它包含了网络设备的各种参数和方法,用于管理网络设备的初始化、配置和操作。

XU157303764的博客 1678

报数游戏(庞果英雄会)

题目来源: 庞果网 题目简介: 一种报数游戏是从1开始连续报数,如果报到7的倍数(7,14,21,28……)或者包含数字7的数(7,17,27,37……)就用拍手代替这个数而不能报出。假设你连续听到m声拍手,问造成你听到m声拍手的第一下拍手所代表的数是几?例如,你听到了两次连续的拍手,最小的可能这两次拍手是27和28,因此输出27。 输入m, 输出这m次连续的拍手第一下所代表的最

XIAXIA__的专栏 1464

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

庞果英雄汇——数组排序

题目详情 本题来自caopengcs,只要你有兴趣,每个人都可以出题(出题入口在主页右侧边栏“贡献题目”->“我要发布”内),以下是题目详情: 给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序。求最少需要多少次交换,能把数组排成按1-n递增的顺序,其中,数组长度不超过100。 例如: 原数组是3,2,1, 我们只需要交换1和3就行了,交换次数为1,所以输

陈明(学习) 1109

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

庞果英雄会——建立信号基站

庞果英雄会——建立信号基站

asd_wolf的专栏 1204

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

庞果英雄会——字符串消除

题目要求 题目详情 给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它,如 有ab或ba连续出现,你把它们替换为字母c; 有ac或ca连续出现时,你可以把它们替换为字母b; 有bc或cb 连续出现时,你可以把它们替换为字母a。 你可以不断反复按照这个规则进行替换,你的目标是使得最终结果

asd_wolf的专栏 1211

庞果英雄会 数组排序

第一次做这个网站的题目   感觉题目还不错   虽然很多题不会  由于是第一次做我还以为只能用给出的头文件     于是自己写了个堆排上去。。。 我感觉看题目的时候就是一个贪心的过程   每次交换的时候都把最大的排好  然后再排下一个   这样就能保证交换次数最少了    至于证明嘛   呵呵  实在是不会啊 下面看代码 #include #include #include #d

泪无痕 570

庞果英雄会部分题目解答

一、数组排序   题目链接:http://hero.pongo.cn/Question/Details?ExamID=92&amp;ID=94&amp;bsh_bid=281776595 题目详情:   给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序。求最少需要多少次交换,能把数组排成按1-n递增的顺序,其中,数组长度不超过100。   例如:   原数组是3,2,...

weixin_34248705的博客 84

庞果网 最小操作数

来源庞果英雄会的挑战题 此题是个图论问题,把A,B与dict里的所有字符串看成图的顶点 求每个顶点的邻接矩阵。 举例如下 "hot"的邻接矩阵为 [hit, null, null, null, null, lot, dot] 根据每个顶点的邻接矩阵组成图 然后求图中的最小路径 得到start节点到图中每一节点的最小路径数组path 然后看这个path数组中path[indexOf

535

庞果英雄会第二届在线编程大赛·线上初赛:AB数

题目链接 给定两个正整数a,b,分别定义两个集合L和R, 集合L:即把1~a,1~b中整数乘积的集合定义为L = {x * y | x,y是整数且1 <= x <=a , 1 <= y <= b}; 集合R:1~a,1~b中整数异或的集合定义为集合R = {x ^ y | x,y是整数且1 <= x <=a , 1 <= y <= b},其中^...

weixin_30315905的博客 83

字符串消除

题目来源:庞果英雄会   题目简介: 给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它,如 有ab或ba连续出现,你把它们替换为字母c; 有ac或ca连续出现时,你可以把它们替换为字母b; 有bc或cb 连续出现时,你可以把它们替换为字母a。 你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的

XIAXIA__的专栏 1907

字符串转换成整数

题目详情 输入一个表示整数的字符串,把该字符串转换成整数并输出,例如输入字符串"345",则输出整数345。 请完成函数StrToInt,实现字符串转换成整数的功能。 友情提醒: 提交代码之前,请复查下你的程序,比如当给的字符串是如左边图片所示的时候,有考虑到么? 当然,它们各自对应的正确输出如右边图片所示(假定你是在32位

晚风心里吹 787

编程之美中构造数独例子

编程之美1.15构造数独 生成一个有效的数独矩阵,只生成一个,可以通过递归将所有有效矩阵都构造出来 #include #include #define NO_MOVE 0 #define AC_MOVE 1 #define NUM 9 typedef struct _CELL { int type; int value; int list[NUM]; int index

asd_wolf的专栏 2154
上一篇: 最短路径算法—Dijkstra算法与Floyd算法
下一篇: 庞果英雄会——回文字符串
asd_wolf
博客等级 码龄18年 38粉丝 21原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值