2018深信服提前批几个笔试

    昨天做了深信服的笔试题,笔试时可能不太习惯,思路很乱,做的不行。现在整理一下几个题。

说明:这些题没有全部的测试案例,不能保证都是可行,只提供一个思路,要是有能够针对提出反例的欢迎提出,一起讨论。

1. 抓兔子


分析:这个题个人感觉就是根据检查的洞编号来躲避查找,能否抓到兔子,就是找到一个抓不到的反例来返回结果

而查找要注意两点:

1)兔子只能往邻域跑,注意边界的处理,

2)下一天兔子的位置避开人的检查,但是可以跑到上一天人检查的位置

#include<iostream>
#include <vector>
#include <queue>
using namespace std;
int main()
{
	int n = 0,  k = 0;
	cin >> n >> k;
	vector<int> vi(k, 0);
	for (int i = 0; i < k; i++)
	{
		cin >> vi[i];
		vi[i]--;
	}
	int rflag = 0;
	for (int j = 0; j < n; j++)
	{
		queue<int> qi;     //存储下一天可能要找的洞
		qi.push(j);
		for (int i = 0; i < k; i++)
		{
			int qiLen = qi.size();
			int cnt = 0;
			while (cnt<qiLen)
			{
				int klabel = qi.front();
				qi.pop();
				cnt++;
				if (vi[i]== klabel)break;    //要找的洞和兔子可能的窝一样,也即是兔子被找到
				if (klabel == 0)
				{
					qi.push(klabel + 1);
				}
				else if(klabel==n-1)
				{
					qi.push(klabel - 1);
				}
				else
				{
					qi.push(klabel + 1);
					qi.push(klabel - 1);
				}
			}
		}
		if (!qi.empty())   //qi非空,表示第k天兔子还没被找到
		{
			rflag = 1;
			while (!qi.empty())
			{
				qi.pop();
			}
			break;
		}
	}
	if (rflag == 1)
		cout << "no" << endl;
	else
		cout << "yes" << endl;
	return 0;
}

例如:4个洞,4次查找 2 2 3 3 ,找不到兔子

5次查找2 2 3 3 2  找到兔子。


2. 选择题目使其分数和为100,唯一解

这个题找不到具体的题目,大概意思就是从一批题目中选出分数和为100 的题目,提供的数据有唯一解。

分析:这其实是个从数组中找出和为定值的组合的一个题目,只不过这个题的组合只有一种,这种题在这个链接里有代码(尊重原创):https://blog.csdn.net/linghuchong2/article/details/71642516

而这个唯一解的问题只需要我们稍加修饰:

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;

int sumto100(vector<int>& vi, vector<int>& re, int sumi, int n)
{
	if (sumi == 0) {
		return true;
	}
	if (sumi < 0)return false;
	if (sumi >= vi[n])
	{
		re.push_back(n);
		if (!sumto100(vi, re, sumi - vi[n], n - 1))
		{
			re.pop_back();
		}
		else
		{
			return true;
		}
	}
	else
	{
		sumto100(vi, re, sumi, n - 1);
	}
	return true;
}

void main()
{
	vector<int> vi = { 1,3,4,12,17,25,35,45 };
	vector<int> re;
	sumto100(vi, re, 100, vi.size() - 1);//re是倒序,题目正序就反过来
	cout << re.size() << endl;
	for (int i=re.size()-1;i>=0;i--)
	{
		cout << re[i] << endl;
	}
	system("pause");
}

例子是随意给的,结果为 4 1 4 6 7 


3. 重复字符串且首尾相连问题:

这个问题开始自己看错了,以为就是简单的重复字符串问题。写的是重复字符串的代码,后来考完经同学提醒才恍然大悟。这个问题当然也可以用暴力收,但是有同学说这样做的测试超时了,也就是复杂度为O(n^3)的可能某些案例过不了。

这个问题其实还是重复字符串问题,在下面这个链接讲的很清楚:

https://www.cnblogs.com/cotyb/p/5211329.html

加上收尾相连这个要求后,还是可以用后缀来做,后缀快排时间复杂度为O(nlog(n)),而后面寻找后缀的最长公共子串(从第一个字符开始相等的最长公共子串)复杂度为O(n*m),m为最长公共子串长度。也即是最后总复杂度为O(nlog(n)+m*n).

并且题设收尾相连重复字符串的长度为二者总长度也即是如:abcabc 长度为6而不是3。故结果较最长重复子串需要做一些修改。

注意:同时后缀排序后两两相邻比较在收尾相连上有一个问题,如果是重复的字符串的比较比如cccc,这样排序是c、cc、ccc、cccc这样的存储加上收尾相连后ccccc重复字符串是只有一个的,cccccc收尾相连才是两个也就是说这里的遍历要根据重复的一个字符串跳着来。

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;


int maxLenStr(string& str)
{
	vector<string> vstr;
	string st;
	for (int i = str.size() - 1; i >= 0; i--)
	{


		st = str[i] + st;
		vstr.push_back(st);
	}
	sort(vstr.begin(), vstr.end());
	int maxlength = 0;
	int k = 1;
	for (int i = 1; i < vstr.size(); i++)
	{


		int cnt = 0;
		while (cnt+1<vstr[i].size()&&vstr[i][cnt]==vstr[i][cnt+1])
		{
			cnt++;
		}
		k = (cnt+1)/ 2;
		k = k >= 1 ? k : 1;     
		cnt = 0;
		while (cnt < vstr[i].size() && cnt < vstr[i - k].size() && vstr[i][cnt] == vstr[i - k][cnt])
		{
			cnt++;
		}
		if (cnt==abs(int(vstr[i].size()-vstr[i-k].size()))&&cnt > maxlength)
		{
			maxlength = cnt;
		}
	}
	//////////////////////////////////////////////////////////////////////////
	return maxlength*2;
}


void main()
{
	string str ="abababcabcabd";
	int len = maxLenStr(str);
	cout << len << endl;
	system("pause");
}

这里结果为6,有两种bcabca和cabcab,





猜你喜欢

转载自blog.csdn.net/song2016/article/details/81062247