第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