字符串系列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wk_bjut_edu_cn/article/details/83655104

剑指Offer(5)--替换空格 

把字符串中出现的每个空格替换成“%20”。

#include<iostream>
using namespace std;
//假设string空间够进行替换
void RelaceString(char *string, int length)
{
	if (string == nullptr || length < 1)
		return;
	int originalLength = 0;
	int spaceNum = 0;
	int i = 0;
	while (string[i] != '\0')
	{
		++originalLength;
		if (string[i] == ' ')
			++spaceNum;
		++i;
	}
	int newLength = originalLength + spaceNum * 2;
	if (newLength < originalLength)
		return;
	//开始时0位置放的是正常的元素,originalLength位置放的'\0'
	while (originalLength >= 0 && newLength>originalLength)
	{
		if (string[originalLength] == ' ')
		{
			string[newLength--] = '0';
			string[newLength--] = '2';
			string[newLength--] = '%';
		}
		else
			string[newLength--] = string[originalLength];
		--originalLength;
	}
}
int main(void)
{
	const int length = 100;
	char str[length] = "hdas l d";
	RelaceString(str, 100);
	for (char i : str)
		cout << i;
	cout << endl;
	system("pause");
	return 0;
}

 剑指Offer(19)--正则表达式匹配

请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。 

思路:

其实就是针对表达式中的*和.以及正常的字符分开来考虑。

#include<iostream>
using namespace std;
bool matchCore(char *str, char *pattern);
bool match(char *string, char *pattern)
{
	if (string == nullptr || pattern == nullptr)
		return false;
	return matchCore(string, pattern);
}
bool matchCore(char *str, char *pattern)
{
	if (*str == '\0' && *pattern == '\0')
		return true;
	if (*str != '\0' && *pattern == '\0')
		return false;
	if (*(pattern + 1) == '*')
	{
		if (*pattern == *str || (*pattern == '.' && *str != '\0'))
		{
			return matchCore(str + 1, pattern + 2)//对应情况是*前面的字符只出现了一次
				|| matchCore(str + 1, pattern)//对应情况是*前面的字符出现了多次或者 *前面出现了.
			/*
			这种情况也会在if中发生
			char str1[] = "abc";
			char str2[] = "a*abc";
			*/
			|| matchCore(str, pattern + 2);
		}
		else
		{
			return matchCore(str, pattern + 2);
		}
	}
	if (*str == *pattern || (*pattern == '.' && *str != '\0'))
		return matchCore(str + 1, pattern + 1);
	return false;
}
int main(void)
{
	char str1[] = "abc";
	char str2[] = "a*abc";
	bool result = match(str1, str2);
	if (result)
		cout << "1" << endl;
	else
		cout << "0" << endl;
	system("pause");
	return 0;
}

 

char firstNotRepeatChar(char *string)
{
	if (string == nullptr)
		return '\0';
	int hashTable[256];
	for (int i = 0; i < 256; ++i)
		hashTable[i] = 0;
	char *str = string;
	while (*str != '\0')
	{
		hashTable[*(str++)]++;
	}
	str = string;
	while (*str != '\0')
	{
		if (hashTable[*str] == 1)
			return *str;
		++str;
	}
	return '\0';
}

剑指Offer(20)--表示数值的字符串

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

思路

这道题还是比较简单的。表示数值的字符串遵循如下模式:

[sign]integral-digits[.[fractional-digits]][e|E[sign]exponential-digits]

其中,('['和']'之间的为可有可无的部分)。

在数值之前可能有一个表示正负的'+'或者'-'。接下来是若干个0到9的数位表示数值的整数部分(在某些小数里可能没有数值的整数部分)。如果数值是一个小数,那么在小数后面可能会有若干个0到9的数位表示数值的小数部分。如果数值用科学记数法表示,接下来是一个'e'或者'E',以及紧跟着的一个整数(可以有正负号)表示指数。

#include<iostream>
using namespace std;
bool scanInteger(char **str);
bool scanIntegerCore(char **str);
bool IsNumber(char *str)
{
	if (str == nullptr)
		return false;
	bool numeric = scanInteger(&str);
	//说明出现了小数部分
	if (*str == '.')
	{
		++str;
		//注意:小数点前面和后面均可以没有数字
		numeric = numeric || scanIntegerCore(&str);
	}
	//说明接下来的数字应该是指数部分
	if (*str == 'e' || *str == 'E')
	{
		++str;
		//e或E的前面必须有数字,e或E的后面必须是整数
		numeric = numeric && scanInteger(&str);
	}
	return numeric && *str == '\0';
}
bool scanInteger(char **str)
{
	if (**str == '+' || **str == '-')
		++(*str);
	return scanIntegerCore(str);
}
bool scanIntegerCore(char **str)
{
	char *before = *str;
	while (**str != '\0' && **str > '\0' && **str <= '9')
		++(*str);
	//如果扫描到了数字,那么返回为true
	return *str > before;
}

剑指Offer(46)--把数字翻译成字符串

给定一个数字,按照如下规则翻译成字符串:0翻译成“a”,1翻译成“b”…25翻译成“z”。一个数字有多种翻译可能,例如12258一共有5种,分别是bccfi,bwfi,bczi,mcfi,mzi。实现一个函数,用来计算一个数字有多少种不同的翻译方法。 

递归版本 

从头到末尾统计,会有大量的重复计算

f(i)=f(i+1)+g(i,i+1)*f(i+2);当第i位和第i+1位两位数字拼接起来的数字在10~25的范围内,函数g(i,i+1)为1,否则为0;

#include<iostream>
#include<string>
using namespace std;
int TranslationCore(const string& number, int i, const int length);
int Translation(int number)
{
	if (number < 0)
		return 0;
	string s = to_string(number);
	int length = s.length();
	return TranslationCore(s,0,length);
}
int TranslationCore(const string& number, int i, const int length)
{
	if (i == length - 1)
		return 1;
	int digit1 = number[i] - '0';
	int digit2 = number[i + 1] - '0';
	int num = digit1 * 10 + digit2;
	//能和下一个结合
	if (num >= 10 && num <= 25)
	{
		if (i == length - 2)
			return 2;
		else
			return TranslationCore(number, i + 1, length) + 
                        TranslationCore(number, i + 2, length);
	}
	else
	{
		//如果不能和下一个结合,那么结果还是下一个
		return TranslationCore(number, i + 1, length);
	}
}
int main(void)
{
	int number = 12258;
	int result = Translation(number);
	cout << result << endl;
	system("pause");
	return 0;
}

非递归版本 

从末尾到头开始统计,这样就不会重复计算

#include<iostream>
#include<string>
using namespace std;
int TranslationCore(const string& number, int i, const int length);
int Translation(int number)
{
	if (number < 0)
		return 0;
	string s = to_string(number);
	int length = s.length();
	return TranslationCore(s,0,length);
}
int TranslationCore(const string& number, int i, const int length)
{
	//用来统计各个下标开始的可以翻译的数目
	int *counts = new int[length];
	int count = 0;
	for (int i = length - 1; i >= 0; --i)
	{
		count = 0;
		if (i < length - 1)
			count = counts[i + 1];
		else
			count = 1;

		if (i < length - 1)
		{
			int digit1 = number[i] - '0';
			int digit2 = number[i+1] - '0';
			int num = digit1 * 10 + digit2;
			if (num >= 10 && num <= 25)
			{
				if (i < length - 2)
					count += counts[i + 2];
				else
					count += 1;
			}
		}
	
		counts[i] = count;
	}
	count = counts[0];
	delete[]counts;
	return count;
}
int main(void)
{
	int number = 12258;
	int result = Translation(number);
	cout << result << endl;
	system("pause");
	return 0;
}

剑指Offer(48)--最长不重复字符的子字符串 

思路:

从string由前到后进行统计,如果没有出现重复的字符,那么curLength就一直++;直到遇上一个先前已经出现过的字符停住进行判断,如果先前已经出现过的那个字符不在当前的curLength范围中,那么CurLength继续++,不受影响。如果出现在当前的curLength范围中,那么判断此时的这个curLength和maxLength的大小关系以进行更新,而且curLength也将从先前出现过的那个字符的后一个字符开始计算。

#include<iostream>
#include<string>
using namespace std;
int SubString(const string& str)
{
	int curLength = 0;
	int maxLength = 0;
	int *posiotion = new int[26];
	for (int i = 0; i < 26; ++i)
		posiotion[i] = -1;
	for (int i = 0; i < str.length(); ++i)
	{
		int prevIndex = posiotion[str[i] - 'a'];
		if (prevIndex<0 || i - prevIndex>curLength)
			++curLength;
		else
		{
			if (curLength > maxLength)
				maxLength = curLength;
			curLength = i - prevIndex;
		}
		posiotion[str[i] - 'a'] = i;
	}
	if (curLength > maxLength)
		maxLength = curLength;

	delete[] posiotion;
	return maxLength;
}

剑指Offer(58)--翻转字符串和左旋转字符串

翻转单词顺序。比如“I am a student” -> "student a am I"

思路:

第一步:翻转句子中的所有字符

第二步:翻转每个单词中字符的顺序

#include<iostream>
using namespace std;
void Reverse(char *begin, char *end)
{
	while (begin < end)
	{
		char temp = *begin;
		*begin = *end;
		*end = temp;
		++begin;
		--end;
	}
}
char *ReverseString(char *string)
{
	if (string == nullptr)
		return nullptr;
	char *m_begin = string;
	char *m_end = string;
	while (*m_end != '\0')
		++m_end;
	--m_end;
	//翻转整个句子
	Reverse(m_begin, m_end);
	m_begin = m_end = string;
	while (*m_begin != '\0')
	{
		if (*m_begin == ' ')
		{
			++m_begin;
			++m_end;
		}
		else if (*m_end == ' ' || *m_end == '\0')
		{
			Reverse(m_begin, --m_end);
			m_begin = ++m_end;
		}
		else
		{
			++m_end;
		}
	}
	return string;
}

左旋转字符串 

输入字符串abcdefg和2,得到cdefgab

思路:

以n为分割点,先旋转前半部分

再旋转后半部分

最后旋转整个字符串

#include<iostream>
using namespace std;
void Reverse(char *begin, char *end)
{
	while (begin < end)
	{
		char temp = *begin;
		*begin = *end;
		*end = temp;
		++begin;
		--end;
	}
}
char *LeftRotateString(char *string, int n)
{
	if (string == nullptr || n < 0)
		return nullptr;
	int length = 0;
	char *str = string;
	while (*str != '\0')
	{
		++length;
		++str;
	}
	if (n > length)
		return nullptr;
	char *firstStart = string;
	char *firstEnd = string + n - 1;
	char *secondStart = string + n;
	char *secondEnd = --str;
	//翻转字符串的前面n个字符
	Reverse(firstStart, firstEnd);
	//翻转字符串的后面部分
	Reverse(secondStart, secondEnd);
	//翻转整个字符串
	Reverse(firstStart, secondEnd);
	return string;
}

剑指Offer(50)--第一个只出现一次的字符

思路:定义哈希表的键值是字符,而值是该字符出现的次数。然后从头开始扫描字符串两次。第一次扫描字符串时,每扫描到一个字符,就在哈希表的对应项中把次数加1.接下来第二次扫描时,每扫描到一个字符,就从哈希表中得到该字符出现的次数。这样,第一个只出现一次的字符就是符合要求的输出。

char FirstNotRepeatingChar(const char* string)
{
	if (string == nullptr)
		return '\0';

	const int tableSize = 256;
    int hashTable[tableSize];
	for (int i = 0; i < tableSize; ++i)
		hashTable[i] = 0;

	const char* pHashKey = string;
	while (*(pHashKey) != '\0')
		hashTable[*(pHashKey++)] ++;

	pHashKey = string;
	while (*pHashKey != '\0')
	{
		if (hashTable[*pHashKey] == 1)
			return *pHashKey;

		pHashKey++;
	}

	return '\0';
}
int main(void)
{
	char string[] = "yaabc";
	char result = FirstNotRepeatingChar(string);
	cout << result << endl;
	system("pause");
	return 0;
}
#include<iostream>
using namespace std;
char firstNotRepeatChar(char *string)
{
	if (string == nullptr)
		return '\0';
	int hashTable[256];
	for (int i = 0; i < 256; ++i)
		hashTable[i] = -1;
	char *str = string;
	int index = 0;
	while (*str != '\0')
	{
		//如果某个字符是第一次出现,赋予以它为下标的值为index(越小代表这个字符越早出现)
		if (hashTable[*str] == -1)
			hashTable[*str] = index;
		//如果某个字符不是第一次出现,赋予以它为下标的值为-2
		else if (hashTable[*str] >= 0)
			hashTable[*str] = -2;
		++ str;
		++index;
	}
	str = string;
	//表示一个很大的数
	int minIndex = 0x7FFFFFFF;
	char ch = '\0';
	for (int i = 0; i < 256; ++i)
	{
		if (hashTable[i] > 0 && hashTable[i] < minIndex)
		{
			ch = (char)(i);
			minIndex = hashTable[i];
		}
	}
	return  ch;
}
int main(void)
{
	char string[] = "ababckc";
	char result = firstNotRepeatChar(string);
	cout << result << endl;
	system("pause");
	return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

注意: 

#include<iostream>
using namespace std;
/*
下面这个代码说明,如果形参是指针,那么在函数中
经过对指针的操作之后,发生变化的是指针指向的位置
的值,而指针所指的位置不会变化,比如下面的str++,
在函数返回时并未发生移动
*/
void fun1(char *str)
{
	*str = 'k';
	str++;
}
void fun2(char *str)
{
	char *str1 = str;
	cout << *str << endl;
	fun1(str);
	cout << *str << endl;
}
int main(void)
{
	char string[] = "abc";
	fun2(string);
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wk_bjut_edu_cn/article/details/83655104
今日推荐