面试题记录

华为面试题:

第1题、给定一个字符串数组,例如[“time”,“me”,“bell”], 然后把字符数据拼接成一个字符串,中间用“#”号键连接,如time#bell#。总长度是10, 字符串解压数组[0,2,5]。(0表示time是 time#bell#从下标0开始到第一个"#“号结束,2表示me是time#bell#从下标2开始到第一个”#"号结束)。只要输出压缩后的长度
输入:[“time”,“me”,“bell”]
输出:10

解题思路:
先分割出单词, 接着筛选字符串,然后拼接,最后计算解压下标数组。时间复杂度O(n^2),空间复杂度O(n)。

代码:

#include 
#include 
#include 

using namespace std;

struct word
{
	string str="";
	int strlen = 0;
	int offset = 0;
	int parent_index = -1;
	int zip_start = 0;
};


void preprocessing(const char str[], vector& vct_words)
{
	int len = strlen(str);
	int index;

	try {
		char *_str = new char[len];
	}
	catch (const bad_alloc& e)
	{
		/// TODO
		return ;
	}


	bool is_start, is_end;

	is_start = false;
	is_end = false;

	for (int i = 0; i < len; ++i)
	{
		if ('\]' == str[i] || '\[' == str[i] || '\,' == str[i])
		{
			continue;
		}

		if ('\"' == str[i])
		{
			if (is_start)
			{
				is_end = true;
			}
			else
			{
				index = 0;
				is_start = true;
				continue;
			}
		}

		if (is_end)
		{
			word _word;
			_str[index] = '\0';
			_word.str = _str;
			_word.strlen = index;
			vct_words.push_back(_word);

			index = 0;
			is_start = false;
			is_end = false;
			continue;
		}

		_str[index++] = str[i];
	}

	delete[] _str;
}


void select_words(vector& vct_words)
{
	string sub_str = "";
	size_t size = vct_words.size();
	int i_strlen, j_strlen;

	for (int i = 0; i < size; ++i)
	{
		i_strlen = vct_words[i].str.length();

		for (int j = 0; j < size; j++)
		{
			j_strlen = vct_words[j].str.length();

			if (i == j || i_strlen >= j_strlen)
			{
				continue;
			}

			// 截取单词尾部固定长度字符串;
			sub_str = vct_words[j].str.substr(j_strlen - i_strlen, i_strlen);

			if (strcmp(vct_words[i].str.c_str(), sub_str.c_str()) != 0)
			{
				continue;
			}
			else
			{
				vct_words[i].parent_index = j;
				vct_words[i].offset = j_strlen - i_strlen;

				// 更新相关单词的引用下标;
				for (int k = 0; k < i; ++k)
				{
					if (vct_words[k].parent_index == i)
					{
						vct_words[k].parent_index = j;
						vct_words[k].offset = vct_words[i].offset + vct_words[k].offset;
					}
				}

				break;
			}
		}
	}
}

void compress(
	const vector& vct_words,
	vector& vct_index,
	string& zip_string, 
	int& zip_len
)
{
	size_t size = vct_words.size();
	zip_string = "";
	zip_len = 0;

	if (0 == size) return;

	vct_index.resize(size);

	// 确定压缩字符串及字符串长度;
	vct_index[0] = 0;
	int cur_start = 0;
	for (int i = 0; i < size; ++i)
	{
		int par_index = vct_words[i].parent_index;
		vct_index[i] = -1;

		if (par_index != -1) continue;

		zip_string += vct_words[i].str + "#";
		vct_index[i] = zip_len;
		zip_len += vct_words[i].strlen + 1;
	}

	// 确定有重叠字符的引用关系;
	for (int i = 0; i < size; ++i)
	{
		int par_index = vct_words[i].parent_index;

		if (par_index == -1) continue;

		vct_index[i] = vct_index[par_index] + vct_words[i].offset;
	}

 }

void display(
	const vector& vct_index,
	const string& zip_string,
	const int& zip_len
)
{
	cout << zip_len << endl;
	cout << zip_string.c_str() << endl;
	cout << "[ ";
	for each(auto item in vct_index)
	{
		cout << item << ", ";
	}
	cout << "]" << endl;
}

int main()
{
	char str[] = "[\"time\", \"me\", \"bell\"]";
	std::vector vct_words;
	std::vector vct_index;
	string zip_string;
	int zip_len;

	// 字符串分解;
	preprocessing(str, vct_words);

	// 筛选出不重复的字符串;
	select_words(vct_words);

	// 压缩;
	compress(vct_words, vct_index, zip_string, zip_len);

	display(vct_index, zip_string, zip_len);

	return 0;
}

第一次现场面,现场上机做题,感觉不是很自然,30分钟内没完成,结束的时候面试官问题了一下解题思路,说完我的想法后嘴贱补了一句“我还没有完全想好”然后就gg了。 这道题感觉细节比较多,比方[“time”,“me”,“bell”,“out”,“hout”,“phout”] 和 [“me”,“me”,“time”,“me”,“bell”,“out”,“hout”,“phout”] 这种时候的拼接和处理。面试结束后自己继续完成了这套题,在这里记录一下。不知道有没有更好的解法,如果网友知道更好的方法,欢迎在评论区交流。

第2题、在整形数组中查找连续最长的子数组,使得了数组的和等于给定的目标值k。
输入:[1,-1,5,-2,3] k = 3
输出:[1,-1,5,-2]

解题思路: 用sum[i]存储前i项的和,找出sum[j]-sum[i] = k的项,比较j-i的最大值,时间复杂度O(n^2),空间复杂度O(n)

代码:

#include 
#include 

using namespace std;
                                                                                                                                                                       

int fun(const vector& arr, int k, int &s, int &e)
{
	vector arr_sum;
	arr_sum.resize(arr.size());

	size_t size = arr.size();

	int sum = 0;
	for (int i = 0; i < size; ++i)
	{
		sum += arr[i];
		arr_sum[i] = sum;
	}

	int max_len = -1,len;
	for (int i = 0; i < size; ++i)
	{
		if (k == arr_sum[i])
		{
			len = e + 1;
			if (len > max_len)
			{
				s = 0;
				e = i;
				max_len = len;
			}
		}

		for (int j = i + 1; j < size; ++j)
		{
			if (arr_sum[j] - arr_sum[i] == k)
			{
				len = e - s + 1;
				if (len > max_len)
				{
					s = i;
					e = j;
					max_len = len;
				}
			}
		}
	}

	if (max_len == -1)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}


int main()
{
	vector arr{ 1, -1, 5, -2, 3 };
	int ret, k = 3, e, s;

	ret = fun(arr, k, s, e);

	if (-1 == ret)
	{
		cout << 0 << endl;
	}
	else
	{
		for (int i = s; i <= e; ++i)
		{
			cout << arr[i] << " ";
		}
		cout << endl;
	}

	return 0;
}

面试官说有时间复杂度O(n)的算法,代码只要10多行。想了一会儿没有想到。网上找了一下第二题,算是一道面试经典题的变式,用哈希表的key存储前i项和,value存储i值,map[sum] = i,表示和为sum的序列为[0,i],假设map[sum-k]的序列为[0,j],那么arr[i ~ j]就是和为sum的连续序列。只要找出[i ~ j]为的最大值序列即可。注意初始化sum_map[0] = -1。

代码:

#include 
#include 

using namespace std;

int main()
{
	int arr[] = { 5, 1, -2, 2, -1, 5, -2, 3 };
	int k = 0, e, s;

	map sum_map;
	int len = sizeof(arr) / sizeof(int);
	
	sum_map[0] = -1;
	int _sum = 0;
	int length = 0;
	for (int i = 0; i < len; ++i)
	{
		_sum += arr[i];

		if (sum_map.find(_sum) == sum_map.end())
		{
			sum_map[_sum] = i;
		}

		if (sum_map.find(_sum - k) != sum_map.end())
		{
			if (length < i-sum_map[_sum - k])
			{
				length = i - sum_map[_sum - k];
				s = sum_map[_sum - k]+1;
				e = i+1;
			}
		}
	}

	for (int i = s; i < e; ++i)
	{
		cout << arr[i] << " ";
	}

	cout << endl;

	return 0;
}

你可能感兴趣的:(面试)