【LeetCode】3.无重复字符串的最长子串

3.无重复字符串的最长子串

一、问题描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

二、问题简化

这个问题本质上是:

“从一个数组中,寻找最长的子串,其元素均不相同”。

这里说下子串和子序列的区别:子串是必须连续的,而子序列不一定连续,但它们的顺序是和原数组相同的。

字符串本质是字符的数组,所以我们使用模板使其更通用化比较恰当。

并且返回值仍然可以是多个

所以整个函数可以表示为:

template<typename T>
vector<T> GetSubLongest(const T& container)

 三、功能实现

1.遍历整个序列,iter0记为下标。

2.从iter0遍历到结束作为子串,或提前出现了不同元素。

3.第2步中保存的子序列,与最长长度判断。如果更长,则删除旧元素,加入自己到结果。如果一样长就只加入自己到结果中。如果更短,iter0自增,进入下一个子串的开始。

template<typename T>
vector<T> GetSubLongest(const T& container)
{
	vector<T> ret;
	int max_size = 0;
	T sub;

	//如果比最大长度长,则加入返回值且更新最大长度
	auto fn_addSub = [&]()
	{
		if (sub.size() > max_size)
		{
			ret.clear();
			ret.push_back(sub);
			max_size = sub.size();
		}
		else if (sub.size() == max_size)
		{
			ret.push_back(sub);
		}
	};

	for (auto iter0 = container.begin(); iter0 != container.end(); ++iter0)
	{
		sub.clear();
		auto iter1 = iter0;
		sub.push_back(*iter0);

		while (true)
		{
			++iter1;
			if (iter1 == container.end())
			{
				//判断加入,然后中断
				fn_addSub();
				break;
			}

			auto iter_f = find(sub.begin(), sub.end(), *iter1);
			if (iter_f == sub.end())
			{//如果不是重复元素,则添加到sub
				sub.push_back(*iter1);
			}
			else
			{//重复了,则检测是否加入到返回值
				//判断加入,然后中断
				fn_addSub();
				break;
			}
		}
	}
	return ret;
}

四、测试结果

//输入值如下:

"我爱中国,中国爱我!"
{ 1,1,2,5,3,2,2,7,8,8,9,1,0 }
"abcabcbb"
"pwwkew"

可以看到,不仅对字符串有用,还对数字有效,甚至于任何事物(只要它们可以比较是否相同),这就是模板泛型算法的魅力。

在判断子序列是否比以往的更长时,由于它会出现两次,所以我写成了lambda表达式。尽量防止代码重复出现,是我编程的原则之一。

还有我使用的是wstring字符串,而不是string。前者是utf-16编码,任何字符都只算一个。如果使用string,中文会算作两个,这样算法就不可能正确处理汉字的相同判断。在使用wcout输出时,需要设置一下本地化环境,调用wcout.imbue(locale("chs"));即可,但这还不是最通用化的写法,暂时这样吧。

完整的代码如下:

//3.无重复字符串的最长子串

#include <iostream>
#include <string>
#include <list>
#include <vector>
using namespace std;

template<typename T>
vector<T> GetSubLongest(const T& container)
{
	vector<T> ret;
	int max_size = 0;
	T sub;

	//如果比最大长度长,则加入返回值且更新最大长度
	auto fn_addSub = [&]()
	{
		if (sub.size() > max_size)
		{
			ret.clear();
			ret.push_back(sub);
			max_size = sub.size();
		}
		else if (sub.size() == max_size)
		{
			ret.push_back(sub);
		}
	};

	for (auto iter0 = container.begin(); iter0 != container.end(); ++iter0)
	{
		sub.clear();
		auto iter1 = iter0;
		sub.push_back(*iter0);

		while (true)
		{
			++iter1;
			if (iter1 == container.end())
			{
				//判断加入,然后中断
				fn_addSub();
				break;
			}

			auto iter_f = find(sub.begin(), sub.end(), *iter1);
			if (iter_f == sub.end())
			{//如果不是重复元素,则添加到sub
				sub.push_back(*iter1);
			}
			else
			{//重复了,则检测是否加入到返回值
				//判断加入,然后中断
				fn_addSub();
				break;
			}
		}
	}
	return ret;
}



int main()
{
	wcout.imbue(locale("chs"));

	//0
	auto ret = GetSubLongest(wstring(L"我爱中国,中国爱我!"));
	for (auto& iter : ret)
	{
		wcout << iter << endl;
	}
	wcout << endl;

	//1
	auto ret1 = GetSubLongest(list<int>({ 1,1,2,5,3,2,2,7,8,8,9,1,0 }));
	for (auto& iter : ret1)
	{
		for (auto& iter1 : iter)
		{
			wcout << iter1;
		}
		wcout << endl;
	}
	wcout << endl;

	//2
	auto ret2 = GetSubLongest(wstring(L"abcabcbb"));
	for (auto& iter : ret2)
	{
		for (auto& iter1 : iter)
		{
			wcout << iter1;
		}
		wcout << endl;
	}
	wcout << endl;

	//3
	auto ret3 = GetSubLongest(wstring(L"pwwkew"));
	for (auto& iter : ret3)
	{
		for (auto& iter1 : iter)
		{
			wcout << iter1;
		}
		wcout << endl;
	}
	wcout << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值