华为2019年3月20日笔试第二题——蛇形字符串

输入一个字符串(不包含空格),请寻找输入中包含的所有蛇形字符串。

蛇形字符串定义:

1、蛇形字符串由连续的字符对组成,其特点如下:

      1.1 字符对定义:字符对由同一字母的大写和小写组成(前大后小),如Aa,Dd

      1.2 蛇形字符串中包含的字符对,必须是连续字母,并按照字母顺序排序。如AaBbCc

2、从输入中寻找字符组成蛇形字符串(字符顺序不限),符合规则:

     2.1 每次寻找必须是最长的蛇形字符串

     2.2 使用过的字符不能重复使用

输入描述:

      一个字符串(不含空格,字符串长度<= 5000)

输出描述:

      1、所有包含的蛇形字符串,按照首字母升序排列(即A在Z前)

      2、同一个首字母的情况,按照蛇形字符串的长度降序输出

      3、如果没有找到输出Not Found

输入示例(自己随便测试的)

DAFHAGFAHFIUHRjkfhbdajfhkEHFUWEIHAJSDKHncnthasrkjhaejsavbdcnskdscnjkdfhgbvsdfdnfkhgj&*(&%^&*(bdvdhjBSDZVBDFBDVH

输出示例:

AaBb
AaBb
AaBb
Aa
DdEeFfGgHh
DdEeFf
Dd
Dd
Dd
Ff
Ff
Ff
Hh
Hh
Hh
Hh
Hh
Hh
JjKk
RrSs
Ss
Vv
Vv

思路:原题目的描述比我写的还要复杂的多,感觉完全是在误导你的思路,而且前面说每次要找最长的蛇形串,后面输出描述又说按照首字母字典序排列。。

所以关键是不要被题目带到坑里去,想的越复杂可能就思路越乱!

我的思路是用C++的map把大写和小写分别存起来,然后以大写的map为准,关键字对应的键值取大写和小写map里面对应的最小值---->> 意思就是:加入说有3个A,2个a,那么你最多组成两个Aa,所以多余就没必要保存了。

然后是,大写的map里面有的字母,对应的小写字母在小写字母map里面找不到,那就erase掉。

第三步:遍历大写的map,每次从头开始查找连续的字母,并且拼接成蛇形串,同时要用一个大写字母,对应的键值就减一;当遇到两个字母不相邻,就退出循环继续从头遍历;遍历开始的时候检查这个字母对应的键值是否为0;如果是则erase掉。直到大写的map为空,退出外层循环。

注意一点是:按照第一步每一轮拼接的蛇形串,按照顺序输出就是题目要求的“按照首字母字典序输出首字母相同就按照长度降序输出”。

C++代码如下:

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

int main()
{
	string s;
	cin >> s;
	map<char, int> mA, ma;//mA存大写字母,ma存小写字母
	for (auto ss : s)
	{
		if(ss >= 'A' && ss <= 'Z') mA[ss]++;
		if(ss >= 'a' && ss <= 'z') ma[ss]++;
	}
	for (auto it = mA.begin(); it != mA.end();)
	{//mA每个关键字对应键值取mA和ma中最小
		if(ma.count(it->first + 32) == 1)
		{
			it++;
		}else mA.erase(it++);//如果ma中没有,则在mA中删除此关键字
	}
	/*for (auto x : mA)//遍历mA中的元素
		cout << x.first << "  " << x.second << endl;*/

	if(mA.empty()){cout << "Not Found" << endl; system("pause"); return 0;}//没有找到

	string tmp;
	map<char, int>::iterator pre, cur;
	while (!mA.empty())
	{
		pre = mA.begin();
		cur = mA.begin();
		if(cur->second == 0)
		{
			mA.erase(cur++);
			continue;
		}
		tmp += cur->first, tmp += cur->first + 32;
		cur->second--;//对应键值减一
		pre = cur, cur++;

		while (cur != mA.end() && cur->second > 0 && cur->first == pre->first + 1)
		{//继续往下查找的条件是没有到达结尾,当前的迭代器指向的键值不为0,并且与上一个字母是相邻的
			tmp += cur->first, tmp += cur->first + 32;
			cur->second--;
			pre++, cur++;
		}
		cout << tmp << endl;
		tmp.clear();
	}
	system("pause");
	return 0;
}

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值