美团点评2016研发工程师在线笔试题题解二

1.最大差值

有一个长为n的数组A,求满足0<=a<=b<n的A[b]-A[a]的最大差值

思路(用贪心可以O(n)时间复杂度):首先设置差值dis=0,最小数组元素min=A[0],从下标为1的元素开始遍历,若A[i]-min>dis,则更新dis,若A[i]<min,则更新min为A[i];因为以后若有一数组元素A[k]-A[i]>dis,那么一定有A[k]-min>A[k]-A[i],去两者差值较大者即A[k]-min;

int getDis(int* A, int n) {
        int dis=0,min=A[0];
        for(int i=1;i<n;i++)
        {
            if(A[i]-min>dis)
                dis=A[i]-min;
            if(A[i]<min)
                min = A[i];
        }
        return dis;
    }

2.棋子翻转

在4x4的棋盘上摆满了黑白棋子,黑白两色的位置和数目随机其中左上角坐标为(1,1),右下角坐标为(4,4),现在依次有一些翻转操作,要对一些给定支点坐标为中心的上下左右四个棋子的颜色进行翻转,请计算出翻转后的棋盘颜色。

给定两个数组Af,分别为初始棋盘和翻转位置。其中翻转位置共有3个。请返回翻转后的棋盘。

测试样例:

[[0,0,1,1],[1,0,1,0],[0,1,1,0],[0,0,1,0]],[[2,2],[3,3],[4,4]]

返回:

[[0,1,1,1],[0,0,1,0],[0,1,1,0],[0,0,1,0]]

思路:其实翻转就是原来为0的变为1,原来为1的变为0,另外要注意给的三个点坐标,横坐标和纵坐标都要减1,因为容器中坐标是从0开始的。如果自己是在边界上,则越过边界的一边不用操作。

vector<vector<int> > flipChess(vector<vector<int> > A, vector<vector<int> > f) {
        for(int i=0;i<3;i++)
        {
            int x = f[i][0]-1;
            int y = f[i][1]-1;
            if(x-1>=0)
            {
                A[x-1][y] = A[x-1][y]==1 ? 0 : 1;
            }
            if(x+1<=3)
            {
                A[x+1][y] = A[x+1][y]==1 ? 0 : 1;
            }
            if(y-1>=0)
            {
                A[x][y-1] = A[x][y-1]==1 ? 0 : 1;
            }
            if(y+1<=3)
            {
                A[x][y+1] = A[x][y+1]==1 ? 0 : 1;
            }
        }
        return A;
    }
3.拜访

现在有一个城市销售经理,需要从公司出发,去拜访市内的商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他只能在左右中选择一个方向,在上下中选择一个方向,现在问他有多少种方案到达商家地址。

给定一个地图map及它的长宽nm,其中1代表经理位置,2代表商家位置,-1代表不能经过的地区,0代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于10。

测试样例:

[[0,1,0],[2,0,0]],2,3

返回:

2

思路:(如果向左走,以后只能向左走,不能向右走,如果向下走,以后只能向下走,不能向上走,如果向其他两个方向走也是一样的)首先遍历一边map,找到经理和商家的位置,设为mx,my,sx,sy,以两者的位置为矩形的两个顶点,即计算两点间有多少种路径。有四种情况:经理的位置在矩形的四个顶点,商家的位置在于经理同一条对角线上的顶点,因为不知道起始位置向哪个方向出发,设两个变量difx,dify,为经理每次走的步长,可以为1,也可以为-1.然后初始化经理所在的行和列,然后从和经理初始位置在同一条对角线上紧邻的位置起,该值只能从它的上左或者上右或者下右或者下左两个位置来,其值等于两个位置值之和,最后返回商家位置即可。

int countPath(vector<vector<int> > map, int n, int m) {
        int mx, my, sx, sy;
	    int difx, dify;
	    for (int i = 0; i < n; i++)
	    {
		    for (int j = 0; j < m; j++)
		    {
			    if (map[i][j] == 1)
			    {
				    mx = i;
				    my = j;
			    }
			    if (map[i][j] == 2)
			    {
				    sx = i;
				    sy = j;
			    }
		    }
	    }
	    difx = mx < sx ? 1 : -1;
	    dify = my < sy ? 1 : -1;
	    for (int i = mx + difx; i != sx + difx; i += difx)
		    map[i][my] = map[i][my] == -1 ? 0 : map[i-difx][my];
	    for (int j = my + dify; j != sy + dify; j += dify)
		    map[mx][j] = map[mx][j] == -1 ? 0 : map[mx][j - dify];
	    for (int i = mx+difx; i != sx+difx; i += difx)
	    {
		    for (int j = my+dify; j != sy+dify; j += dify)
		    {
			    map[i][j] = map[i][j] == -1 ? 0 : map[i - difx][j] + map[i][j - dify];
		    }
	    }
	    return map[sx][sy];
    }

4.直方图内最大矩阵

有一个直方图,用一个整数数组表示,其中每列的宽度为1,求所给直方图包含的最大矩形面积。比如,对于直方图[2,7,9,4],它所包含的最大矩形的面积为14(即[7,9]包涵的7x2的矩形)。

给定一个直方图A及它的总宽度n,请返回最大矩形面积。保证直方图宽度小于等于500。保证结果在int范围内。

测试样例

[2,7,9,4,1],5
返回:
14

思路:用的方法是时间复杂度为O(n^2)量级的,依次以数组中每个元素为最小高度计算所能组成的最大直方图的面积,比较之后选取最大的即可。对于其中某个元素A[i],首先向后遍历,如果A[i+1]>A[i],则A[i+1]可以组成以A[i]为高的直方图,继续向后遍历,直到某个元素值小于A[i]时,break跳出循环。然后从A[i]处向前遍历,如果A[i-1]>A[i],则A[i-1]也可以组成以A[i]为底的直方图,继续向前遍历,直到某个元素小于A[i]为止。

int countArea(vector<int> A, int n) {
    int maxarea = 0;
	int cnt = 0;
	for (int i = 0; i < n; i++)
	{
		int num = A[i];
		cnt = 0;
		for (int j = i; j < n; j++)
		{
			if (A[j] >= num)
				cnt++;
			else
				break;
		}
        for(int k=i-1;k>=0;k--)
        {
            if(A[k]>=num)
                cnt++;
            else
                break;
        }
		int area = num*cnt;
		if (maxarea < area)
			maxarea = area;
	}
	return maxarea;
    }
};

5.见上一篇博客点击打开链接

6.平均年龄

已知某公司总人数为W,平均年龄为Y岁(每年3月末计算,同时每年3月初入职新人),假设每年离职率为x,x>0&&x<1,每年保持所有员工总数不变进行招聘,新员工平均年龄21岁。 

从今年3月末开始,请实现一个算法,可以计算出第N年后公司员工的平均年龄。(最后结果向上取整)。

输入描述:

输入W Y x N

输出描述:

输出第N年后的平均年龄

示例

输入:

5 5 0.2 3

输出:

15

思路:其实本体就两个部分,一个是年龄求解公式,一个是整型向上取整。平均年龄可以用所有人的年龄数之和除以总人数W,设今年公司总人数W,平均年龄Y,离职率为x,一年后,平均年龄要加1,则一年后除去离职的人,总人数为W*(1-x)总年龄数为总人数乘以平均年龄则为W*(1-x)*(Y+1)为了保持总人数不变,则来年招聘人数为W*x,新招聘人员总年龄为W*x*21。因此总年龄数为W*(1-x)*(Y+1)+W*x*21,除以总人数W即为平均年龄 newY=(W*(1-x)*(Y+1)+W*x*21)/W。N年以后则将公式循环计算N次即可求出,最后向上取整。

#include<iostream>
#include<math.h>
using namespace std;
int main()
{
	double Y,x;
	int W,N;
	while (cin >> W >> Y >> x >> N)
	{
		double newY;
		for (int i = 1; i <= N; i++)
		{
			newY = (W*(1 - x)*(Y + 1) + x*W * 21) / W;
			Y = newY;
		}
		int y = Y;
		if (y == Y)
			cout << y << endl;
		else
			cout << y + 1 << endl;
	}
	return 0;
}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值