第一题:单词最近距离
题目:
有一篇文章内含多个单词,现给定两个单词,请设计一个高效算法,找出文中这两个单词的最短距离(即最少相隔的单词数,也就是两个单词在文章中位置的差的绝对值)。
给定一个string数组article,代表所给文章,同时给定文章的单词数n和待查找的两个单词x和y。请返回两个单词的最短距离。保证两个单词均在文中出现且不相同,同时保证文章单词数小于等于1000。
解析:
class Distance {
public:
int getDistance(vector<string> article, int n, string x, string y) {
// write code here
int distance = 1000;
int t1 = 2000; int t2 = 1000;
for (int i = 0; i < n; ++i) {
if (article[i] == x) t1 = i;
if (article[i] == y) t2 = i;
distance = abs(t1 - t2) < distance ? abs(t1 - t2) : distance;
}
return distance;
}
};
第二题:最长合成字符串
题目:
有一组单词,请编写一个程序,在数组中找出由数组中字符串组成的最长的串A,即A是由其它单词组成的(可重复)最长的单词。
给定一个string数组str,同时给定数组的大小n。请返回最长单词的长度,保证题意所述的最长单词存在。
测试样例:
[“a”,“b”,“c”,“ab”,“bc”,“abc”],6
返回:
3
解析:
class LongestString {
public:
static bool cmp(string str1,string str2)
{
return str1.size()>str2.size();
}
int getLongest(vector<string> str, int n) {
// write code here
sort(str.begin(),str.end(),cmp);
for(int i=0;i<n;++i)
{
string temp = str[i];
int x;
for(int j=i+1;j<n;++j)
{
while((x=temp.find(str[j]))!=-1)
{
temp.erase(x,str[j].size());
}
}
if(temp.empty()) return str[i].size();
}
return -1;
}
};
第三题:子串判断
题目:
现有一个小写英文字母组成的字符串s和一个包含较短小写英文字符串的数组p,请设计一个高效算法,对于p中的每一个较短字符串,判断其是否为s的子串。
给定一个string数组p和它的大小n,同时给定string
s,为母串,请返回一个bool数组,每个元素代表p中的对应字符串是否为s的子串。保证p中的串长度小于等于8,且p中的串的个数小于等于500,同时保证s的长度小于等于1000。
测试样例:
[“a”,“b”,“c”,“d”],4,“abc”
返回:
[true,true,true,false]
解析:
注意:find()函数的用法
,str.find(str, beg=0, end=len(string))
- str – 指定检索的字符串
- beg – 开始索引,默认为0。
- end – 结束索引,默认为字符串的长度。
如果包含子字符串返回开始的索引值,否则返回-1。
参考链接
class Substr {
public:
vector<bool> chkSubStr(vector<string> p, int n, string s) {
// write code here
vector<bool> res(n,false);
for (int i = 0; i < n; ++i) {
if (s.find(p[i]) != -1) {
res[i] = true;
}
}
return res;
}
};
第四题:实时中位数
题目:
现有一些随机生成的数字要将其依次传入,请设计一个高效算法,对于每次传入一个数字后,算出当前所有传入数字的中位数。(若传入了偶数个数字则令中位数为第n/2小的数字,n为已传入数字个数)。
给定一个int数组A,为传入的数字序列,同时给定序列大小n,请返回一个int数组,代表每次传入后的中位数。保证n小于等于1000。
测试样例:
[1,2,3,4,5,6],6
返回:
[1,1,2,2,3,3]
解析:
class Middle {
public:
vector<int> getMiddle(vector<int> A, int n) {
// write code here
vector<int> sorted;
vector<int> output;
for (int i = 0; i < n; i++) {
vector<int>::iterator iter = sorted.begin();
for ( ; iter != sorted.end(); iter++) {
if (A[i] <= *iter){
break;
}
}
sorted.insert(iter, A[i]);
output.push_back(sorted[i/2]);
}
return output;
}
};
class Middle {
public:
vector<int> getMiddle(vector<int> a, int n) {
// write code here
vector<int> res(n);
res[0]=a[0];
for(int i=1;i<n;i++){
int temp=a[i];
int j;
for(j=i-1;j>=0&&temp<a[j];j--){
a[j+1]=a[j];
}
a[j+1]=temp;
res[i]=a[i/2];
}
return res;
}
};
第五题:字符串变换
题目:
现有一个字典,同时给定字典中的两个字符串s和t,给定一个变换,每次可以改变字符串中的任意一个字符,请设计一个算法,计算由s变换到t所需的最少步数,同时需要满足在变换过程中的每个串都是字典中的串。
给定一个string数组dic,同时给定数组大小n,串s和串t,请返回由s到t变换所需的最少步数。若无法变换到t则返回-1。保证字符串长度均小于等于10,且字典中字符串数量小于等于500。
测试样例:
[“abc”,“adc”,“bdc”,“aaa”],4,”abc”,“bdc”
返回:
2
解析:
class Change {
bool difOne(string const& a, string const& b) {
int cnt = 0;
for (int i(0), size(a.size()); i < size; ++i) {
if (a[i] != b[i]) ++cnt;
}
return cnt == 1;
}
bool checkIn(vector<string> const& dic, int n, string const& s, string const& t) {
bool sIn = false, tIn = false;
for (int i = 0; i < n; ++i) {
if (dic[i] == s) sIn = true;
if (dic[i] == t) tIn = true;
}
return sIn && tIn;
}
public:
int countChanges(vector<string> const& dic, int n, string const& s, string const& t) {
if (s.size() != t.size() || !checkIn(dic, n, s, t)) return -1;
if (s == t) return 0;
list<string> unused;
copy_if(dic.begin(), dic.end(), back_inserter(unused),
[&s](string const& str) { return str != s && str.size() == s.size(); });
queue<string> que;
que.push(s);
for (int level = 1; que.size(); ++level) {
for (int i(que.size()); i > 0; --i) {
string const& cur = que.front();
for (auto it = unused.begin(); it != unused.end(); ) {
if (difOne(cur, *it)) {
if (*it == t) return level;
que.push(*it);
it = unused.erase(it);
} else {
++it;
}
}
que.pop();
}
}
return -1;
}
};
第六题:最大子方阵
题目:
有一个方阵,其中每个单元(像素)非黑即白(非0即1),请设计一个高效算法,找到四条边颜色相同的最大子方阵。
给定一个01方阵mat,同时给定方阵的边长n,请返回最大子方阵的边长。保证方阵边长小于等于100。
测试样例:
[[1,1,1],[1,0,1],[1,1,1]],3
返回:
3
解析:
遍历所有,对每一个可能的长度进行验证
class SubMatrix {
public:
int maxSubMatrix(vector<vector<int> > mat, int n) {
// write code here
int maxLength = n;
while (maxLength) {
for (int i = 0; i <= n - maxLength; ++i) {
for (int j = 0; j <= n - maxLength; ++j) {
int pixel = mat[i][j];
bool flag = true;
for (int k = 0; k < maxLength; ++k) {
int top = mat[i][j + k]; // 上边的线
int bottom = mat[i + maxLength - 1][j + k]; // 下边的线
int left = mat[i + k][j]; // 左边的线
int right = mat[i + k][j + maxLength - 1]; // 右边的线
if (top != pixel || bottom != pixel || left != pixel || right != pixel) {
flag = false;
break;
}
}
if (flag) return maxLength;
}
}
maxLength--;
}
return 0;
}
};
第七题:最大和子矩阵
题目:
有一个正整数和负整数组成的NxN矩阵,请编写代码找出元素总和最大的子矩阵。请尝试使用一个高效算法。
给定一个int矩阵mat和矩阵的阶数n,请返回元素总和最大的子矩阵的元素之和。保证元素绝对值小于等于100000,且矩阵阶数小于等于200。
测试样例:
[[1,2,-3],[3,4,-5],[-5,-6,-7]],3
返回:
10
解析:
对每一行,与下面行累加,得到一个一维数组,用一维数组求连续子数组的最大和的方式求出最大和
class SubMatrix {
public:
int sumOfSubMatrix(vector<vector<int> > mat, int n) {
// write code here
int maxsum=0,submax=0;
for(int time=0;time<n;time++)
{
vector<int> v(n,0);
for(int i=time;i<n;i++)
{
submax=0;
for(int j=0;j<n;j++)
{
v[j]+=mat[i][j];
submax=max(v[j],v[j]+submax);
maxsum=max(maxsum,submax);
}
}
}
return maxsum;
}
};
第八题:最大字母矩阵
题目:
有一个单词清单,请设计一个高效算法,计算由清单中单词组成的最大子矩阵,要求矩阵中的行和列都是清单中的单词。
给定一个string数组dic,代表单词清单,同时给定清单的大小n,请返回最大子矩阵的面积。保证单词清单的大小小于等于50,且某一长度的串的数量小于等于12。
测试样例:
[“aaa”,“aaa”,“aaa”,“bb”,“bb”]
返回:
9
解析:
class AlphaMatrix {
public:
int findAlphaMatrix(vector<string> dic, int n) {
// write code here
set<string> temp;
int res = 0;
for(int i = 0; i < n; i++){
string word = dic[i];
if(temp.find(word)!= temp.end())continue;
temp.insert(word);
int count = 1;
for(int j = i + 1; j < n; j++){
string word2 = dic[j];
if(word.compare(word2))break;
++count;
}
i += count - 1;
if(count * word.size() > res)res = count * word.size();
}
return res;
}
};