字符串系列

目录

 

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

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

 

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

剑指Offer(38)--字符串的排列

打印一个字符串的全部子序列,包括空字符串

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

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

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

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

字符串切割

最长回文子串

注意: 

求两个字符串的最长公共子串

求两个字符串的最长公共子序列


剑指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;
    //注意:*str == '\0' && *pattern != '\0'这种情况有可能是true
    //比如:str=a,pattern=a*
	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;
/*
扫描字符串中的0-9的位数,如果属于0-9,则++,否则停止,
最后判断是否在这个字符串中出现过0-9
*/
bool scanUnsignedInteger(const char **str)
{
	const char *before = *str;
	while (**str != '\0' && **str >= '0' && **str <= '9')
		++(*str);
	//如果为true,说明有过移动,说明出现过数字
	return *str > before;
}
/*
扫描可能以正负的'+'或者'-'为起始的0-9的数值
*/
bool scanInteger(const char **str)
{
	if (**str == '+' || **str == '-')
		++(*str);
	return scanUnsignedInteger(str);
}
bool isNumeric(const char *str)
{
	if (str == nullptr)
		return false;
	bool numeric = scanInteger(&str);
	if (*str == '.')
	{
		++str;
		//小数点前面或者后面有数字就行
		//scanUnsignedInteger(&str)是在判断小数点后面是否有数字
		numeric = scanUnsignedInteger(&str) || numeric;
	}
	if (*str == 'e' || *str == 'E')
	{
		++str;
		//e的前面必须有数字,e的整数部分必须是整数
		//scanInteger(&str)是在判断e的后面是否为整数
		numeric = numeric && scanInteger(&str);
	}
	return numeric && *str == '\0';
}
int main(void)
{
	char *c1 = "12e+5";
	if (isNumeric(c1))
		cout << "yes" << endl;
	else
		cout << "no" << endl;
	system("pause");
	return 0;
}

剑指Offer(38)--字符串的排列

题目

输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 

#include<iostream>
#include<string>
using namespace std;
/*
打印一个字符串的全部排列

思路:第二个位置和以后的位置,轮流来坐第一个位置,
生成字符串,然后,这些固定了第一个位置的字符串
再按照同样的方式确定第二个字符串(第三个及以后的
轮流来做第二个位置)
*/
void printAllPermutations(string str,int i)
{
	if (i == str.size()-1)
	{
		cout << str << endl;
		return;
	}
	for (int j = i; j < str.size(); ++j)
	{
		swap(str[i], str[j]);
		printAllPermutations(str, i + 1);
	}
}
int main(void)
{
	string test = "abyc";
	printAllPermutations(test, 0);
	system("pause");
	return 0;
}

打印一个字符串的全部子序列,包括空字符串

#include<iostream>
#include<string>
using namespace std;
/*
打印一个字符串的全部子序列,包括空字符串
思路:
每次遇到字符,就分两种进行递归,一种是要这个字符
另一种是不要
*/
//递归的第一步,先要想到如何终止
void printAllSub(string &str, int i, string &res)
{
	if (i == str.size())
	{
		cout << res << endl;
		return;
	}
	//选择不要这个字符
	printAllSub(str, i + 1, res);
	//选择要这个字符
	printAllSub(str, i + 1, res + str[i]);
}

int main(void)
{
	string test = "abc";
	string s = "";
	printAllSub(test, 0, s);
	system("pause");
	return 0;
}

剑指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;
}

非递归版本-动态规划

int numDecodings(string s)
{
	int length = s.length();
	if (length == 0 || s[0] == '0')
		return 0;
	vector<int> v(length, 0);
	v[0] = 1;
	for (int i = 1; i < length; ++i)
	{
		if (s[i] != '0')
			v[i] = v[i - 1];
		if (s[i - 1] == '1' || s[i - 1] == '2' && s[i] >= '0' && s[i] <= '6')
		{
			if (i == 1)
				v[i] += 1;
			else
				v[i] += v[i - 2];
		}
	}
	return v[length - 1];
}

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

题目:

请从字符串中找出一个最长的不包含重复数字的子字符串,计算该最长子字符串的长度。假设字符串中仅包含 ‘a’~’z’ 之间的字符。例如,在字符串 “arabcacfr” 中,最长的不包含重复字符的子字符串是 “rabc” 或 “acfr”,所以应当输出 4。

思路:

从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为分割点,先旋转前半部分

再旋转后半部分

最后旋转整个字符串

右旋字符串

输入字符串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;
}

字符串切割

void split(const char *s, vector<string> &strs, char delim = ' ') {
    if(s == nullptr) {
        return;
    }

    const char *head, *tail;
    head = tail = s;

    while(*head != '\0') {
        while(*head != '\0' && *head == delim) {
            head++;
        }

        tail = head;
        while(*tail != '\0' && *tail != delim) {
            tail++;
        }

        if(head != tail) {
            strs.push_back(string(head, tail));
            head = tail;
        } else {
            break;
        }
    }
}
int main()
{
	char *s = "ddsa das eqw 23 g gf";
	vector<string> vs;
	split(s, vs);
	for (auto i : vs)
		cout << i << endl;
	system("pause");
	return 0;
}

最长回文子串

思路一:

中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。

但是要考虑两种情况:

1、像aba,这样长度为奇数。

2、像abba,这样长度为偶数。

所以得走两遍,都看一下。

string findLongestPalindrome(string s)
{
	int length = s.size();
	int maxLength = 0;
	int start = 0;
	//当字符串的长度为奇数
	for (int i = 0; i < length; ++i)
	{
		int j = i - 1, k = i + 1;
		while (j >= 0 && k < length &&s[j] == s[k])
		{
			if (k - j + 1 > maxLength)
			{
				maxLength = k - j + 1;
				start = j;
			}
			--j;
			++k;
		}
	}
	//当字符串的长度为偶数
	for (int i = 0; i < length; ++i)
	{
		int j = i , k = i + 1;
		while (j >= 0 && k < length &&s[j] == s[k])
		{
			if (k - j + 1 > maxLength)
			{
				maxLength = k - j + 1;
				start = j;
			}
			--j;
			++k;
		}
	}
	if (maxLength > 0)
		return s.substr(start, maxLength);
}

思路二:动态规划

/*
动态规划法,时间复杂度为O(n^2),空间复杂度为O(n^2)
*/
string longestPalindrome(string s)
{
	int const n = s.size();
	vector<vector<bool>> v(n, vector<bool>(n, false));
	size_t maxLength = 1;//最长回文子串的长度
	size_t start = 0;//最长回文子串的起点
	for (size_t i = 0; i < s.size(); ++i)
	{
		v[i][i] = true;
		for (size_t j = 0; j < i; ++j)
		{
			//v[j][i]==true;说明s字符串在i-j区间内为回文结构
			//i-j<2说明是相邻的相等,这也算回文
			v[j][i] = (s[j] == s[i] && (i - j < 2 || v[j + 1][i - 1]));
			if (v[j][i] && maxLength < (i - j + 1))
			{
				maxLength = i - j + 1;
				start = j;
			}
		}
	}
	return s.substr(start, maxLength);
}

 

注意: 

#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;
}

求两个字符串的最长公共子串

最长公共子串要求在原字符串中是连续的,而子序列只需要保持相对顺序一致,并不要求连续。

动态规划解题,状态转移方程如下:

问题:有两个字符串str和str2,求出两个字符串中最长公共子串长度。

比如:str=acbcbcef,str2=abcbced,则str和str2的最长公共子串为bcbce,最长公共子串长度为5。

#include<iostream>
#include<vector>
#include<string>
using namespace std;
string getLCS(string str1, string str2)
{
	int maxLen = 0, maxEnd = 0;
	int m = str1.size(), n = str2.size();
	vector<vector<int>> record(m + 1 , vector<int>(n + 1, 0));
	for (int i = 1; i <= m; ++i)
	{
		for (int j = 1; j <= n; ++j)
		{
			if (str1[i-1] == str2[j-1])
				record[i][j] = record[i - 1][j - 1] + 1;
			else
				record[i][j] = 0;
			if (record[i][j]>maxLen)
			{
				maxLen = record[i][j];
				maxEnd = i - 1;
			}
		}
	}
	return str1.substr(maxEnd - maxLen + 1, maxLen);
}
int main(void)
{
	string str1 = "acbctbcef", str2 = "abcbced";
	cout << getLCS(str1, str2) << endl;
	system("pause");
	return 0;
}

原文地址:https://blog.csdn.net/qq_25800311/article/details/81607168

求两个字符串的最长公共子序列

动态规划解题,状态转移方程如下:

int longestSubstring(string s1, string s2) 
{
	if (s1.size() == 0 || s2.size() == 0)
		return 0;
	int m = s1.size(), n = s2.size();
	vector<vector<int>> v(m + 1, vector<int>(n + 1, 0));
	for (int i = 1; i <= m; ++i)
	{
		for (int j = 1; j <= n; ++j)
			if (s1[i - 1] == s2[j - 1])
				v[i][j] = v[i - 1][j - 1] + 1;
			else
				v[i][j] = v[i - 1][j] > v[i][j - 1] ? v[i - 1][j] : v[i][j - 1];
	}
	return v[m][n];
}

上面的程序是没有得出最长子序列,只是得出了长度;如果求解最长子序列,则需要进行记录。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int longestSubstring(string s1, string s2, vector<vector<int>> &v, vector<vector<char>> &help)
{
	if (s1.size() == 0 || s2.size() == 0)
		return 0;
	int m = s1.size(), n = s2.size();
	v.resize(m + 1);
	help.resize(m + 1);
	for (int i = 0; i < v.size(); ++i)
		v[i].resize(n + 1);
	for (int i = 0; i < help.size(); ++i)
		help[i].resize(n + 1);
	for (int i = 1; i <= m; ++i)
	{
		for (int j = 1; j <= n; ++j)
			if (s1[i - 1] == s2[j - 1])
			{
				v[i][j] = v[i - 1][j - 1] + 1;
				help[i][j] = 'c';//标记
			}
			else if (v[i - 1][j] >= v[i][j - 1]) {
				v[i][j] = v[i - 1][j];
				help[i][j] = 'u';//从上边下来的
			}
			else {
				v[i][j] = v[i][j-1];
				help[i][j] = 'l';//从左边下来的
			}
	}
	return v[m][n];
}
void print_lcs(vector< vector<char>> &help, string s, int m, int n)
{
	if (m == 0 || n == 0)
		return;
	if (help[m][n] == 'c') {
		print_lcs(help, s, m - 1, n - 1);
		cout << s[n - 1];
	}
	else if (help[m][n] == 'u')
		print_lcs(help, s, m - 1, n);
	else
		print_lcs(help, s, m, n - 1);
}
int main()
{
	string s1 = "afhgta";
	string s2 = "fktsad";
	vector< vector<int>> v;
	vector< vector<char>> help;
	int result = longestSubstring(s1, s2, v, help);
	cout<<result<<endl;
	print_lcs(help, s2, s1.size(), s2.size());
	system("pause");
	return 0;
}

最长递增子序列

问题

给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4。

解法1:最长公共子序列法

这个问题可以转换为最长公共子序列问题。如例子中的数组A{5,6, 7, 1, 2, 8},则我们排序该数组得到数组A‘{1, 2, 5, 6, 7, 8},然后找出数组A和A’的最长公共子序列即可。显然这里最长公共子序列为{5, 6, 7, 8},也就是原数组A最长递增子序列。

解法2:动态规划法(时间复杂度O(N^2))

设长度为N的数组为{a0,a1, a2, ...an-1),则假定以aj结尾的数组序列的最长递增子序列长度为L(j),则L(j)={ max(L(i))+1, i<j且a[i]<a[j] }。也就是说,我们需要遍历在j之前的所有位置i(从0到j-1),找出满足条件a[i]<a[j]的L(i),求出max(L(i))+1即为L(j)的值。最后,我们遍历所有的L(j)(从0到N-1),找出最大值即为最大递增子序列。时间复杂度为O(N^2)。

例如给定的数组为{5,6,7,1,2,8},则L(0)=1, L(1)=2, L(2)=3, L(3)=1, L(4)=2, L(5)=4。所以该数组最长递增子序列长度为4,序列为{5,6,7,8}。算法代码如下:

#include<iostream>
#include<vector>
using namespace std;
int LongestIncreSubseq(const vector<int> &v)
{
	int size = v.size();
	vector<int> record(size, 1);
	for (int j = 1; j < size; ++j)
	{
		for (int i = 0; i < j; ++i)
			if (v[j]>v[i] && record[j] < record[i] + 1)
				record[j] = record[i] + 1;
	}
	int result = 0;
	for (int i = 0; i < size; ++i)
	{
		if (record[i] > result)
			result = record[i];
	}
	return result;
}
int main()
{
	vector<int> v { 1, 4, 5, 6, 2, 3, 8 }; //测试数组  
	cout << LongestIncreSubseq(v) << endl;
	system("pause");
	return 0;
}

最长公共前缀

#include<iostream>
#include<vector>
#include<string>
using namespace std;
/*
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
*/
string longestCommonPrefix(vector<string>& strs)
{
	string result = "";
	if (strs.empty())
		return result;
	string s1 = strs[0];
	for (int i = 0; i < s1.size();++i)
	{
		for (int j = 1; j < strs.size(); ++j)
		{
			if (s1[i] != strs[j][i])
				return result;			
		}
		result += s1[i];
	}
	return result;
}

字符串匹配

int ViolentMatch(string s, string p)
{
	int len1 = s.size();
	int len2 = p.size();
	int i = 0, j = 0;
	while (i < len1 && j < len2)
	{
		if (s[i] == s[j])
		{
			++i;
			++j;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
	}
	if (j == p.size())
		return i - j;
	else
		return -1;
}

字符串相加

string addStrings(string num1, string num2) {
        string res = "";
        int m = num1.size(), n = num2.size(), i = m - 1, j = n - 1, carry = 0;
        while (i >= 0 || j >= 0) {
            int a = i >= 0 ? num1[i--] - '0' : 0;
            int b = j >= 0 ? num2[j--] - '0' : 0;
            int sum = a + b + carry;
            res.insert(res.begin(), sum % 10 + '0');
            carry = sum / 10;
        }
        return carry ? "1" + res : res;
    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值