链家网-后台开发工程师笔试题-第三题

序言(废话)

今天做链家网的笔试题, 选择题考的好杂好杂啊, php, java, C++ 几乎是等比重的考察,完全没有侧重,完全没有侧重。 幸亏都是基本语法, 大部分只要用心猜(反正编程语言都差不多了,毕竟咱是学C++的, 什么邪恶的写法没见过~~~~)。

然后是笔试题, 其实笔试题三道都挺简单的, 只不过第三道题会卡时间。

题目描述

小恪要给学校里的人分组, 每个人的编号是连续的正整数(从1开始)。 然后根据某些同学的编号,查询它在哪个组里。

输入描述

第一行输入正整数 n, 代表总共有几数, 然后下一行输入 n 个正整数,表示每一个组有几个成员。
第三行输入正整数m, 代表有 m 次的询问。 然后下一行有 m 个正整数, 表示询问编号为 Mi的成员,在哪一组?

5
2 7 3 4 9
3
1 25 11

题目输出

1
5
3

数据范围

1<= N <= 10^5, 1<= 每个组的成员数量 <= 10^6, 1<= M <= 10^5.

解题代码

方法一: 直接做

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <stdexcept>
using namespace std;

const int maxn = 100000 + 5; 
long long arr[maxn]; 
long long brr[maxn]; 

int main()
{
	int n; 
	cin >> n; 
	arr[0] = 0; 
	for(int i = 1; i <= n; i++)
		cin >> arr[i]; 
	for(int i = 2; i <= n; i++)
		arr[i] = arr[i] + arr[i-1]; 
	
	int m; 
	cin >> m; 
	for(int i = 1; i <= m; i++)
		cin >> brr[i]; 
	for(int i = 1; i <= m; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			if(arr[j] >= brr[i])
			{
				cout << j << endl; 
				break; 
			}
		}
	}		
	
	return 0; 
}

在规定的时间内,通过了 82%样例。 也就是说稍微有些超时~~~

方法二: 用二分查找代替顺序查找

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxn = 100000 + 5; 
long long arr[maxn]; 
long long brr[maxn]; 

int bSearch(long long arr[], int left, int right, long long val)
{
	while(left < right)
	{
		int mid = left + (right - left)/2;
		if(arr[mid] < val)
			left = mid+1; 
		else if(arr[mid] > val)
			right = mid; 
		else
			return mid; 
	} 
	
	return left; 
}

int main()
{
	int n; 
	cin >> n; 
	arr[0] = 0; 
	for(int i = 1; i <= n; i++)
		cin >> arr[i]; 
	for(int i = 2; i <= n; i++)
		arr[i] = arr[i] + arr[i-1]; 
	
	int m; 
	cin >> m; 
	for(int i = 1; i <= m; i++)
		cin >> brr[i]; 
	for(int i = 1; i <= m; i++)
	{
		cout << bSearch(arr, 1, n+1, brr[i]) << endl; 
	}		
	
	return 0; 
}

然而结果仍然是 82%, 好坑啊, 数据好没区分度啊!!!, 本来以为这种程度的优化绝壁就能过了, 于是就没打算写下面的第三种方法,结果。。。。悲剧了!!!!

方法三: 空间换时间, 排序+hash

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
using namespace std;

const int maxn = 100000 + 5; 
long long arr[maxn]; 
long long brr[maxn]; 
long long crr[maxn]; 

int main()
{
	int n; 
	cin >> n; 
	arr[0] = 0; 
	for(int i = 1; i <= n; i++)
		cin >> arr[i]; 
	for(int i = 2; i <= n; i++)
		arr[i] = arr[i] + arr[i-1]; 
	
	int m; 
	cin >> m; 
	for(int i = 1; i <= m; i++)
	{
		cin >> brr[i]; 
		crr[i] = brr[i]; 
	}
		
	unordered_map<long long, long long> mm; 
	sort(crr+1, crr+m+1);
	int pos = 1;  
	int i = 1; 
	while(i <= n)
	{
		if(pos > m)
			break; 
			
		while(arr[i] < crr[pos])
			i++; 
		mm[crr[pos]] = i; 
		pos++; 	
	}		
	
	for(int i = 1; i <= m; i++)
		cout << mm[brr[i]] << endl; 
		
	return 0; 
}

毫无疑问, 这个提交绝不会超时,因为时间复杂度是O(NlogN)啊, 并且没有常数因子, 线段树也只能是这样的复杂度了吖。 但是, 但是, 链家网用的笔试OJ好差啊, 提交一个题目要十分钟 ~ ~ 。


听说由于这个原因, 最后延时半小时 ~ ~ ~, 可是我已经提前交卷了, ~ ~ ~, 感觉好坑啊。 (当然主要还是怪自己没有再等等 ~ ~ ~)。 写篇博客,总结一下教训,不喜勿喷~~。



posted @ 2017-08-19 21:46  草滩小恪  阅读(204)  评论(0编辑  收藏