字符串

目录:

20、【剑指Offer学习】【面试题20:表示数值的字符串】

38、【剑指Offer学习】【面试题38:字符串的排列】

46、【剑指Offer学习】【面试题46:把数字翻译成字符串】

48、【剑指Offer学习】【面试题48:最长不含重复字符的子字符串】

50、【剑指Offer学习】【面试题50:字符串中第一个只出现一次的字符】

67、【剑指Offer学习】【面试题67:把字符串转换成整数】

20. 表示数值的字符串

	/*******************************************************************
	Copyright(c) 2016, Harry He
	All rights reserved.

	Distributed under the BSD license.
	(See accompanying file LICENSE.txt at
	https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
	*******************************************************************/

	//==================================================================
	// 《剑指Offer——名企面试官精讲典型编程题》代码
	// 作者:何海涛
	//==================================================================

	// 面试题20:表示数值的字符串
	// 题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,
	// 字符串“+100”、“5e2”、“-123”、“3.1416”及“-1E-16”都表示数值,但“12e”、
	// “1a3.14”、“1.2.3”、“+-5”及“12e+5.4”都不是

	#include <stdio.h>

	bool scanUnsignedInteger(const char** str);
	bool scanInteger(const char** str);

	// 数字的格式可以用A[.[B]][e|EC]或者.B[e|EC]表示,其中A和C都是
	// 整数(可以有正负号,也可以没有),而B是一个无符号整数
	bool isNumeric(const char* str)
	{
		if(str == nullptr)
			return false;

		bool numeric = scanInteger(&str);

		// 如果出现'.',接下来是数字的小数部分
		if(*str == '.')
		{
			++str;

			// 下面一行代码用||的原因:
			// 1. 小数可以没有整数部分,例如.123等于0.123;
			// 2. 小数点后面可以没有数字,例如233.等于233.0;
			// 3. 当然小数点前面和后面可以有数字,例如233.666
			numeric = scanUnsignedInteger(&str) || numeric;
		}

		// 如果出现'e'或者'E',接下来跟着的是数字的指数部分
		if(*str == 'e' || *str == 'E')
		{
			++str;

			// 下面一行代码用&&的原因:
			// 1. 当e或E前面没有数字时,整个字符串不能表示数字,例如.e1、e1;
			// 2. 当e或E后面没有整数时,整个字符串不能表示数字,例如12e、12e+5.4
			numeric = numeric && scanInteger(&str);
		}

		return numeric && *str == '\0';
	}

	bool scanUnsignedInteger(const char** str)
	{
		const char* before = *str;
		while(**str != '\0' && **str >= '0' && **str <= '9')
			++(*str);

		// 当str中存在若干0-9的数字时,返回true
		return *str > before;
	}

	// 整数的格式可以用[+|-]B表示, 其中B为无符号整数
	bool scanInteger(const char** str)
	{
		if(**str == '+' || **str == '-')
			++(*str);
		return scanUnsignedInteger(str);
	}

	// ====================测试代码====================
	void Test(const char* testName, const char* str, bool expected)
	{
		if(testName != nullptr)
			printf("%s begins: ", testName);

		if(isNumeric(str) == expected)
			printf("Passed.\n");
		else
			printf("FAILED.\n");
	}


	int main(int argc, char* argv[])
	{
		Test("Test1", "100", true);
		Test("Test2", "123.45e+6", true);
		Test("Test3", "+500", true);
		Test("Test4", "5e2", true);
		Test("Test5", "3.1416", true);
		Test("Test6", "600.", true);
		Test("Test7", "-.123", true);
		Test("Test8", "-1E-16", true);
		Test("Test9", "1.79769313486232E+308", true);

		printf("\n\n");

		Test("Test10", "12e", false);
		Test("Test11", "1a3.14", false);
		Test("Test12", "1+23", false);
		Test("Test13", "1.2.3", false);
		Test("Test14", "+-5", false);
		Test("Test15", "12e+5.4", false);
		Test("Test16", ".", false);
		Test("Test17", ".e1", false);
		Test("Test18", "e1", false);
		Test("Test19", "+.", false);
		Test("Test20", "", false);
		Test("Test21", nullptr, false);

		return 0;
	}

38. 面试题38:字符串的排列

			/*******************************************************************
			Copyright(c) 2016, Harry He
			All rights reserved.

			Distributed under the BSD license.
			(See accompanying file LICENSE.txt at
			https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
			*******************************************************************/

			//==================================================================
			// 《剑指Offer——名企面试官精讲典型编程题》代码
			// 作者:何海涛
			//==================================================================

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

			#include <cstdio>

			void Permutation(char* pStr, char* pBegin);

			void Permutation(char* pStr)
			{
				if(pStr == nullptr)
					return;

				Permutation(pStr, pStr);
			}

			void Permutation(char* pStr, char* pBegin)
			{
				if(*pBegin == '\0')
				{
					printf("%s\n", pStr);
				}
				else
				{
					for(char* pCh = pBegin; *pCh != '\0'; ++ pCh)
					{
						char temp = *pCh;
						*pCh = *pBegin;
						*pBegin = temp;

						Permutation(pStr, pBegin + 1);

						temp = *pCh;
						*pCh = *pBegin;
						*pBegin = temp;
					}
				}
			}

			// ====================测试代码====================
			void Test(char* pStr)
			{
				if(pStr == nullptr)
					printf("Test for nullptr begins:\n");
				else
					printf("Test for %s begins:\n", pStr);

				Permutation(pStr);

				printf("\n");
			}

			int main(int argc, char* argv[])
			{
				Test(nullptr);

				char string1[] = "";
				Test(string1);

				char string2[] = "a";
				Test(string2);

				char string3[] = "ab";
				Test(string3);

				char string4[] = "abc";
				Test(string4);

				return 0;
			}

46. 面试题46:把数字翻译成字符串

			/*******************************************************************
			Copyright(c) 2016, Harry He
			All rights reserved.

			Distributed under the BSD license.
			(See accompanying file LICENSE.txt at
			https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
			*******************************************************************/

			//==================================================================
			// 《剑指Offer——名企面试官精讲典型编程题》代码
			// 作者:何海涛
			//==================================================================

			// 面试题46:把数字翻译成字符串
			// 题目:给定一个数字,我们按照如下规则把它翻译为字符串:0翻译成"a",1翻
			// 译成"b",……,11翻译成"l",……,25翻译成"z"。一个数字可能有多个翻译。例
			// 如12258有5种不同的翻译,它们分别是"bccfi"、"bwfi"、"bczi"、"mcfi"和
			// "mzi"。请编程实现一个函数用来计算一个数字有多少种不同的翻译方法。

			#include <string>
			#include <iostream>

			using namespace std;

			int GetTranslationCount(const string& number);

			int GetTranslationCount(int number)
			{
				if(number < 0)
					return 0;

				string numberInString = to_string(number);
				return GetTranslationCount(numberInString);
			}

			int GetTranslationCount(const string& number)
			{
				int length = number.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 converted = digit1 * 10 + digit2;
						if(converted >= 10 && converted <= 25)
						{
							if(i < length - 2)
								count += counts[i + 2];
							else
								count += 1;
						}
					}

					counts[i] = count;
				}

				count = counts[0];
				delete[] counts;

				return count;
			}

			// ====================测试代码====================
			void Test(const string& testName, int number, int expected)
			{
				if(GetTranslationCount(number) == expected)
					cout << testName << " passed." << endl;
				else
					cout << testName << " FAILED." << endl;
			}

			void Test1()
			{
				int number = 0;
				int expected = 1;
				Test("Test1", number, expected);
			}

			void Test2()
			{
				int number = 10;
				int expected = 2;
				Test("Test2", number, expected);
			}

			void Test3()
			{
				int number = 125;
				int expected = 3;
				Test("Test3", number, expected);
			}

			void Test4()
			{
				int number = 126;
				int expected = 2;
				Test("Test4", number, expected);
			}

			void Test5()
			{
				int number = 426;
				int expected = 1;
				Test("Test5", number, expected);
			}

			void Test6()
			{
				int number = 100;
				int expected = 2;
				Test("Test6", number, expected);
			}

			void Test7()
			{
				int number = 101;
				int expected = 2;
				Test("Test7", number, expected);
			}

			void Test8()
			{
				int number = 12258;
				int expected = 5;
				Test("Test8", number, expected);
			}

			void Test9()
			{
				int number = -100;
				int expected = 0;
				Test("Test9", number, expected);
			}

			int main(int argc, char* argv[])
			{
				Test1();
				Test2();
				Test3();
				Test4();
				Test5();
				Test6();
				Test7();
				Test8();
				Test9();

				return 0;
			}

48. 面试题48:最长不含重复字符的子字符串

		/*******************************************************************
		Copyright(c) 2016, Harry He
		All rights reserved.

		Distributed under the BSD license.
		(See accompanying file LICENSE.txt at
		https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
		*******************************************************************/

		//==================================================================
		// 《剑指Offer——名企面试官精讲典型编程题》代码
		// 作者:何海涛
		//==================================================================

		// 面试题48:最长不含重复字符的子字符串
		// 题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子
		// 字符串的长度。假设字符串中只包含从'a'到'z'的字符。

		#include <string>
		#include <iostream>

		// 方法一:蛮力法
		bool hasDuplication(const std::string& str, int position[]);

		int longestSubstringWithoutDuplication_1(const std::string& str)
		{
			int longest = 0;
			int* position = new int[26];
			for(int start = 0; start < str.length(); ++start)
			{
				for(int end = start; end < str.length(); ++end)
				{
					int count = end - start + 1;
					const std::string& substring = str.substr(start, count);
					if(!hasDuplication(substring, position))
					{
						if(count > longest)
							longest = count;
					}
					else
						break;

				}
			}

			delete[] position;
			return longest;
		}

		bool hasDuplication(const std::string& str, int position[])
		{
			for(int i = 0; i < 26; ++i)
				position[i] = -1;

			for(int i = 0; i < str.length(); ++i)
			{
				int indexInPosition = str[i] - 'a';
				if(position[indexInPosition] >= 0)
					return true;

				position[indexInPosition] = indexInPosition;
			}

			return false;
		}

		// 方法一:动态规划
		int longestSubstringWithoutDuplication_2(const std::string& str)
		{
			int curLength = 0;
			int maxLength = 0;

			int* position = new int[26];
			for(int i = 0; i < 26; ++i)
				position[i] = -1;

			for(int i = 0; i < str.length(); ++i)
			{
				int prevIndex = position[str[i] - 'a'];
				if(prevIndex < 0 || i - prevIndex > curLength)
					++curLength;
				else
				{
					if(curLength > maxLength)
						maxLength = curLength;

					curLength = i - prevIndex;
				}
				position[str[i] - 'a'] = i;
			}

			if(curLength > maxLength)
				maxLength = curLength;

			delete[] position;
			return maxLength;
		}

		// ====================测试代码====================
		void testSolution1(const std::string& input, int expected)
		{
			int output = longestSubstringWithoutDuplication_1(input);
			if(output == expected)
				std::cout << "Solution 1 passed, with input: " << input << std::endl;
			else
				std::cout << "Solution 1 FAILED, with input: " << input << std::endl;
		}

		void testSolution2(const std::string& input, int expected)
		{
			int output = longestSubstringWithoutDuplication_2(input);
			if(output == expected)
				std::cout << "Solution 2 passed, with input: " << input << std::endl;
			else
				std::cout << "Solution 2 FAILED, with input: " << input << std::endl;
		}

		void test(const std::string& input, int expected)
		{
			testSolution1(input, expected);
			testSolution2(input, expected);
		}

		void test1()
		{
			const std::string input = "abcacfrar";
			int expected = 4;
			test(input, expected);
		}

		void test2()
		{
			const std::string input = "acfrarabc";
			int expected = 4;
			test(input, expected);
		}

		void test3()
		{
			const std::string input = "arabcacfr";
			int expected = 4;
			test(input, expected);
		}

		void test4()
		{
			const std::string input = "aaaa";
			int expected = 1;
			test(input, expected);
		}

		void test5()
		{
			const std::string input = "abcdefg";
			int expected = 7;
			test(input, expected);
		}

		void test6()
		{
			const std::string input = "aaabbbccc";
			int expected = 2;
			test(input, expected);
		}

		void test7()
		{
			const std::string input = "abcdcba";
			int expected = 4;
			test(input, expected);
		}

		void test8()
		{
			const std::string input = "abcdaef";
			int expected = 6;
			test(input, expected);
		}

		void test9()
		{
			const std::string input = "a";
			int expected = 1;
			test(input, expected);
		}

		void test10()
		{
			const std::string input = "";
			int expected = 0;
			test(input, expected);
		}

		int main(int argc, char* argv[])
		{
			test1();
			test2();
			test3();
			test4();
			test5();
			test6();
			test7();
			test8();
			test9();
			test10();

			return 0;
		}

50. 面试题50:字符串中第一个只出现一次的字符

		/*******************************************************************
		Copyright(c) 2016, Harry He
		All rights reserved.

		Distributed under the BSD license.
		(See accompanying file LICENSE.txt at
		https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
		*******************************************************************/

		//==================================================================
		// 《剑指Offer——名企面试官精讲典型编程题》代码
		// 作者:何海涛
		//==================================================================

		// 面试题50(一):字符串中第一个只出现一次的字符
		// 题目:在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出
		// 'b'。

		#include <cstdio>
		#include <string>

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

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

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

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

				pHashKey++;
			}

			return '\0';
		}

		// ====================测试代码====================
		void Test(const char* pString, char expected)
		{
			if(FirstNotRepeatingChar(pString) == expected)
				printf("Test passed.\n");
			else
				printf("Test failed.\n");
		}

		int main(int argc, char* argv[])
		{
			// 常规输入测试,存在只出现一次的字符
			Test("google", 'l');

			// 常规输入测试,不存在只出现一次的字符
			Test("aabccdbd", '\0');

			// 常规输入测试,所有字符都只出现一次
			Test("abcdefg", 'a');

			// 鲁棒性测试,输入nullptr
			Test(nullptr, '\0');

			return 0;
		}

		/*******************************************************************
		Copyright(c) 2016, Harry He
		All rights reserved.

		Distributed under the BSD license.
		(See accompanying file LICENSE.txt at
		https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
		*******************************************************************/

		//==================================================================
		// 《剑指Offer——名企面试官精讲典型编程题》代码
		// 作者:何海涛
		//==================================================================

		// 面试题50(二):字符流中第一个只出现一次的字符
		// 题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从
		// 字符流中只读出前两个字符"go"时,第一个只出现一次的字符是'g'。当从该字
		// 符流中读出前六个字符"google"时,第一个只出现一次的字符是'l'。

		#include <cstdio>
		#include <vector>
		#include <limits>

		using namespace std;

		class CharStatistics
		{
		public:
			CharStatistics() : index(0)
			{
				for(int i = 0; i < 256; ++i)
					occurrence[i] = -1;
			}

			void Insert(char ch)
			{
				if(occurrence[ch] == -1)
					occurrence[ch] = index;
				else if(occurrence[ch] >= 0)
					occurrence[ch] = -2;

				index++;
			}

			char FirstAppearingOnce()
			{
				char ch = '\0';
				int minIndex = numeric_limits<int>::max();
				for(int i = 0; i < 256; ++i)
				{
					if(occurrence[i] >= 0 && occurrence[i] < minIndex)
					{
						ch = (char) i;
						minIndex = occurrence[i];
					}
				}

				return ch;
			}

		private:
			// occurrence[i]: A character with ASCII value i;
			// occurrence[i] = -1: The character has not found;
			// occurrence[i] = -2: The character has been found for mutlple times
			// occurrence[i] >= 0: The character has been found only once
			int occurrence[256];
			int index;
		};

		// ====================测试代码====================
		void Test(const char* testName, CharStatistics chars, char expected)
		{
			if(testName != nullptr)
				printf("%s begins: ", testName);

			if(chars.FirstAppearingOnce() == expected)
				printf("Passed.\n");
			else
				printf("FAILED.\n");
		}

		int main(int argc, char* argv[])
		{
			CharStatistics chars;

			Test("Test1", chars, '\0');

			chars.Insert('g');
			Test("Test2", chars, 'g');

			chars.Insert('o');
			Test("Test3", chars, 'g');

			chars.Insert('o');
			Test("Test4", chars, 'g');

			chars.Insert('g');
			Test("Test5", chars, '\0');

			chars.Insert('l');
			Test("Test6", chars, 'l');

			chars.Insert('e');
			Test("Test7", chars, 'l');

			return 0;
		}

67. 面试题67:把字符串转换成整数

		/*******************************************************************
		Copyright(c) 2016, Harry He
		All rights reserved.

		Distributed under the BSD license.
		(See accompanying file LICENSE.txt at
		https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
		*******************************************************************/

		//==================================================================
		// 《剑指Offer——名企面试官精讲典型编程题》代码
		// 作者:何海涛
		//==================================================================

		// 面试题67:把字符串转换成整数
		// 题目:请你写一个函数StrToInt,实现把字符串转换成整数这个功能。当然,不
		// 能使用atoi或者其他类似的库函数。

		#include <cstdio>

		long long StrToIntCore(const char* str, bool minus);

		enum Status {kValid = 0, kInvalid};
		int g_nStatus = kValid;

		int StrToInt(const char* str)
		{
			g_nStatus = kInvalid;
			long long num = 0;

			if(str != nullptr && *str != '\0') 
			{
				bool minus = false;
				if(*str == '+')
					str ++;
				else if(*str == '-') 
				{
					str ++;
					minus = true;
				}

				if(*str != '\0') 
					num = StrToIntCore(str, minus);
			}

			return (int)num;
		}

		long long StrToIntCore(const char* digit, bool minus)
		{
			long long num = 0;

			while(*digit != '\0') 
			{
				if(*digit >= '0' && *digit <= '9') 
				{
					int flag = minus ? -1 : 1;
					num = num * 10 + flag * (*digit - '0');

					if((!minus && num > 0x7FFFFFFF) 
						|| (minus && num < (signed int)0x80000000))
					{
						num = 0;
						break;
					}

					digit++;
				}
				else 
				{
					num = 0;
					break;
				}
			}

			if(*digit == '\0') 
				g_nStatus = kValid;

			return num;
		}

		// ====================测试代码====================
		void Test(const char* string)
		{
			int result = StrToInt(string);
			if(result == 0 && g_nStatus == kInvalid)
				printf("the input %s is invalid.\n", string);
			else
				printf("number for %s is: %d.\n", string, result);
		}

		int main(int argc, char* argv[])
		{
			Test(nullptr);

			Test("");

			Test("123");

			Test("+123");
			
			Test("-123");

			Test("1a33");

			Test("+0");

			Test("-0");

			//有效的最大正整数, 0x7FFFFFFF
			Test("+2147483647");    

			Test("-2147483647");

			Test("+2147483648");

			//有效的最小负整数, 0x80000000
			Test("-2147483648");    

			Test("+2147483649");

			Test("-2147483649");

			Test("+");

			Test("-");

			return 0;
		}
posted @ 2019-12-11 20:18  风御之举  阅读(23)  评论(0编辑  收藏  举报