网易2019校招笔试题
##1. 丰收
题目:
就是堆了几堆的南瓜,然后给出几个数字作为序号,猜是第几堆里面的南瓜
思路:
思路不难,就是进行累加,然后找出数字在第几个堆里。让人不爽的是时间复杂度败给了调用函数的,就是这个lower_bound(first *itor,last *itor,const int T)
函数,它指向在[first,last]
标记的有序序列中可以插入value
,而不会破坏容器顺序的第一个位置,而这个位置标记了一个不小于value
的值
###代码:
#include <bits/stdc++.h>
using namespace std;
int sum[100005];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int a;
scanf("%d", &a);
sum[i] = sum[i - 1] + a;
}
int q;
scanf("%d", &q);
while (q--) {
int d;
scanf("%d", &d);
int pos = lower_bound(sum, sum + n + 1, d) - sum;
printf("%d\n", pos);
}
return 0;
}
##2. 瞌睡
题目:
就是一个傻逼小孩上课打瞌睡,然后还想让同桌叫醒他,让他再学那么几分钟,让我们求这个傻逼小孩上课收益最大(能听到课内容最多)
思路:
思路不难,就是滑动窗口的动态规划,这个听了好多次,但是没有务实地学会。
###代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n), t(n);
for (int i = 0; i < n; i++)
cin >> a[i];
int now = 0;
for (int i = 0; i < n; i++)
cin >> t[i], now += t[i] * a[i];
int res = now;
for (int i = 0; i < n;) {
now += (!t[i]) * a[i];
if (++i >= k) {
res = max(res, now);
now -= (!t[i - k]) * a[i - k];
}
}
cout << res << endl;
return 0;
}
今日头条2019校招笔试题
##1. 求矩形的最大连通域
题目:
球场团队数与最大团队的人数
思路:
bfs,参考leetcode 200. Number of Islands。要注意的是输入,用逗号隔开,解决方法是每次读取一个数后,都调用cin.get()来清除逗号
###代码:
void bfs(vector<vector<int>>& grid, int i, int j, int& num)
{
if (i<0 || i>grid.size() - 1 || j<0 || j>grid[0].size() - 1 || grid[i][j] == 0)
return;
grid[i][j] = 0;
++num;
bfs(grid, i - 1, j, num);
bfs(grid, i + 1, j, num);
bfs(grid, i, j - 1, num);
bfs(grid, i, j + 1, num);
bfs(grid, i - 1, j - 1, num);
bfs(grid, i - 1, j + 1, num);
bfs(grid, i + 1, j - 1, num);
bfs(grid, i + 1, j + 1, num);
return;
}
int main()
{
int M, N;
cin >> M;
cin.get();
cin >> N;
vector<vector<int> > grid(M, vector<int>(N, 0));
for (int i = 0; i < M; ++i)
{
for (int j = 0; j < N; ++j)
{
cin >> grid[i][j];
cin.get();
}
}
int num = 0, maxNum = 0;
for (int i = 0; i != M; ++i)
{
for (int j = 0; j != N; ++j)
if (grid[i][j] == 1)
{
int tmpMax = 0;
bfs(grid, i, j, tmpMax);
++num;
if (tmpMax > maxNum)
maxNum = tmpMax;
}
}
cout << num << "," << maxNum << endl;
return 0;
}
##2. 区间合并
题目:
有多人给出区间,每个人给出多个,要求合并
思路:
先排序,排序规则是先左端点升序,相同时右端点升序。leetcode好像有做过类似的。。ps:这道题的分号逗号有点恶心,要单独处理下。
###代码:
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
struct Interval {
long long start;
long long end;
Interval() : start(0), end(0) {}
Interval(long long s, long long e) : start(s), end(e) {}
};
bool com(const Interval& a, const Interval& b)
{
if (a.start != b.start)
return a.start < b.start;
if (a.end != b.end)
return a.end < b.end;
return false;
}
void SplitString(const string& s, vector<string>& v, const string& c)
{
string::size_type pos1, pos2;
pos2 = s.find(c);
pos1 = 0;
while (string::npos != pos2)
{
v.push_back(s.substr(pos1, pos2 - pos1));
pos1 = pos2 + c.size();
pos2 = s.find(c, pos1);
}
if (pos1 != s.length())
v.push_back(s.substr(pos1));
}
int main()
{
int m;
cin >> m;
vector<Interval> intervals;
for (int i = 0; i < m; ++i)
{
string s;
cin >> s;
vector<string> v;
SplitString(s, v, ";");
int num = v.size();
for (int j = 0; j < num; ++j)
{
vector<string> v0;
SplitString(v[j], v0, ",");
Interval x;
x.start = stoi(v0[0]);
x.end = stoi(v0[1]);
intervals.push_back(x);
}
}
sort(intervals.begin(), intervals.end(), com);
long long len = intervals.size();
vector<Interval> res;
long long start(0);
long long end(0);
for (long long i = 0; i < len;)
{
start = intervals[i].start;
end = intervals[i].end;
long long j = i + 1;
for (; j < len; ++j)
{
if (end < intervals[j].start)
break;
end = max(end, intervals[j].end);
}
res.push_back(Interval(start, end));
i = j;
}
long long len2 = res.size();
for (long long i = 0; i < len2; ++i)
{
cout << res[i].start << ',' << res[i].end;
if (i != len2 - 1)
cout << ';';
}
}
搜狐2019校招笔试题
##1. 亲密子串
题目:
兄弟串的定义:通过交换两个字符得到的字符串,如A="abc"其兄弟串是“acb”,“bac”,“cba”。给定两个由小写字母组成的字符串A和B,判断他们是否为兄弟串,是就返回1,不是就返回0
思路:
基本的思路就是先看有没有重复的,有重复的就直接将相应的元素不输入到set中,如果不是重复的,就看两个是否相等,如果不相等就进行计数,看不相等的数字个数是否为2,不为2也不对,如果为2了,就将相应的存进去的下标提取出来,将两个字符串指定位置的字符进行比较,都相等就是对的。
###代码:
class Solution {
public:
bool buddyStrings(string A, string B) {
if(A.empty() || B.empty()){
return false;
}
if(A.size() != B.size()){
return false;
}
vector<int> index;
set<char> seen;
bool res1=false;
for(int i=0; i<A.size(); i++){
if(seen.count(A[i])){
res1 = true;
}
else{
seen.insert(A[i]);
}
if(A[i] != B[i]){
index.push_back(i);
}
}
if(index.empty()){
return res1;
}
else{
if(index.size() != 2){
return false;
}
return (A[index[0]] == B[index[1]] && A[index[1]] == B[index[0]]);
}
}
};
##2. 计算移动次数
题目:
假设有一个无限长的x轴,你站在原点x=0处,要去往的目标点是x轴上的任意一个整数点,但是每次移动,只能向左或者向右,而且第N次移动就移动N的距离。现给定一个目标点target,要求为了到达目标点,移动最少次数。
思路:
这道题非常有意思,主要考察看问题的角度。这道题本质上就是一个递增序列改变加减号得到最终结果。所以可以这么来做,先将递增序列一直加,加到大于等于目标值,如果正好等于目标值,那么就直接等于那个值。如果大于那个目标值,就分两种情况考虑,如果超过的值和目标值的差值是偶数,就直接等于走的步数(因为只要调整某一步的值,就可以得到一个偶数的偏差值);如果超过的值和目标值的差值是奇数,就分两种一个是当前的步数是奇数,那么就不用凑出1(奇数和偶数的差值),如果当前的步数是偶数,那么就需要用下一步来凑出这个差值1
###代码:
class Solution {
public:
/**
* @param target: the destination
* @return: the minimum number of steps
*/
int reachNumber(int target) {
// Write your code here
target = abs(target);
int step = 1, pos = 0;
while (pos < target) {
pos += step;
step++;
}
step--;
if (pos == target) return step;
pos -= target;
if (pos % 2 == 0) {
return step;
} else if ((step + 1) % 2 == 1) {
return step + 1;
} else {
return step + 2;
}
}
};
##3. 比较版本号大小
题目:
比较两个版本号version1和version2,if version1>version2 return 1;if version1 < version2 return -1; other return 0;
思路:
版本号比对,还是比较简单的,开始的时候比较小数点之前的数字的大小相同的话,就将计数置为零,重新开始计数,如果输入的版本号后面不存在的话,可以直接往后遍历,因为长度不符合要求的字符串的计数直接就是0。
###代码:
class Solution {
public:
int compareVersion(string version1, string version2) {
int n1 = version1.size(), n2 = version2.size();
int i = 0, j = 0, d1 = 0, d2 = 0;
while (i < n1 || j < n2) {
while (i < n1 && version1[i] != '.') {
d1 = d1 * 10 + version1[i++] - '0';
}
while (j < n2 && version2[j] != '.') {
d2 = d2 * 10 + version2[j++] - '0';
}
if (d1 > d2) return 1;
else if (d1 < d2) return -1;
d1 = d2 = 0;
++i; ++j;
}
return 0;
}
};