2018春笔试题总结

百度笔试的编程题有三道,岗位是移动软件开发工程师,都不是复杂的算法题,三道题AC了两道,考察递归多一点。

第一道题是排列组合的题:有n个国家的参赛队伍,每只队伍有5个选手,现在吧这些所有的选手排成一队,要求是每位选手的旁边是自己国家的人,问有多少种不同的排列方法,随着n变大,这个结果会很大,实际结果可以对一个数据取余输出,我忘了是多少了。比如只有一个国家那就有5*4*3*2*1=120种不同的方法。这道题没做出来。

第二道题说有一个国王,另外给出一个m*n的地图,用m*n的矩阵表示,矩阵元素都是整数表示高度,给出国王在地图中的起始位置,国王可以随便上下左右移动,但是这个国王很烦只愿意移动到不低于当前高度的位置,问最后国王可以在这幅地图里面可以达到最高的位置。


回溯法,递归的时候函数返回判断条件是移动到了矩阵的边界就返回上一次函数,小于上一次的位置也返回。

每一次递归的时候不往回走重复的路。判断移动方向的坐标和传递进来坐标不同才可以进行递归。

#include<stdio.h>

#define MAX_N	200
#define MAX_M	200

int array[MAX_N][MAX_M] = {0};
int n;
int m;
static int max_height = 0;

void func(int old_x, int old_y, int new_x, int new_y);

void func(int old_x, int old_y, int new_x, int new_y) {
	static int max_height;
	if(new_x < 0 || new_x >= n || new_y < 0 || new_y >= m) {
		return ;
	}
	if(array[new_x][new_y] < array[old_x][old_y]) {
		return;
	}
	if(new_y - 1 != old_y) {   //判断
		func(new_x, new_y, new_x, new_y - 1);		
	}
	if(new_y + 1 != old_y) {
		func(new_x, new_y, new_x, new_y + 1);		
	}
	if(new_x - 1 != old_x) {
		func(new_x, new_y, new_x - 1, new_y);		
	}
	if(new_x + 1 != old_x) {
		func(new_x, new_y, new_x + 1, new_y);		
	}

	max_height = array[new_x][new_y] >  max ? array[new_x][new_y] : max;
}

int main(void) {
	int sx;
	int sy;
	int x;
	int i;
	int j;

	scanf("%d%d", &n, &m);
	scanf("%d%d", &sx, &sy);
	for(i = 0; i < n; i++) {
		for(j = 0; j < m; j++) {
			scanf("%d", &array[i][j]);	
		}
	}

	func(sx - 1, sy - 1, sx - 1, sy - 1);
	printf("%d\n", max_height);	

	return 0;
}

第三题也是一道递归的题,题目是这么说的,阴阳师里面得到一个3星式神需要3个2个式神合成,4星式神需要4个3星式神,以此类推,问得到一个32星的式神需要多少个2星式神,具体多少星我忘了,一开始做没考虑最后int会爆掉的情况。只过了67%的数据,后来仔细一想这个数据远远超过了long类型,就用java大数类解决掉了。

就是一道纯粹的递归,f(n) = n * f(n - 1) ,当n=2的时候f(n) = 1

import java.math.BigInteger;

public class Baidu_Demo {
	private static final BigInteger two = new BigInteger("2");
	
	private static BigInteger fun(BigInteger n) {
		if(n.compareTo(two) != 1) {
			return BigInteger.ONE;
		}
		
		return n.multiply(fun(n.subtract(BigInteger.ONE)));
	}

	public static void main(String[] args) {
		System.out.println(fun(new BigInteger("32")));
	}
}

其他做的笔试题有:

判断一个无序数组中是否有两个数之和为给定的值,比如在一个数组{4,2,5,6,-23,5,9,7}中是否有两个数字之和为15,要求时间复杂度O(n)。

最直接就是上双层循环,但是时间复杂度达到了O(n^2)不可取;先排序再用双指针头尾开始找,排序需要O(nlogn),双指针找的过程需要O(n),总的需要O(nlogn),但是超出了要求;

最后的思路是用哈希表。就可以达到O(n)。先把数组中所有的元素放进去HashMap中,键值都是数组的值,但是遍历一遍数组。查找15-array[i]这个值是否存在HashMap中。存在就说明可以有两个数之和为15,反之则不存在这样的两个数。

当时做的时候想到了HashMap,没有想着用,它是一个现成的工具,有点走捷径一样。

import java.util.HashMap;

public class Main {
	private static boolean func(int array[]) {
		HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
		
		for(int x :array) {
			map.put(x, x);
		}
		for(int i = 0; i < array.length; i++) {
			if(map.get(15-array[i]) != null) {
				return true;
			}
		}

		return false;
	}
	
	public static void main(String[] args) {	
		int array[] = {4,6,2,1,7,9,2,3,4};
		
		boolean result = func(array);
		
		System.out.println(result);
	}

给出多组坐标数据(x,y),每组数据有4个,问这一组数据能否构成一个正方形(腾讯笔试模拟题)。

四个点能否构成一个正方形,四条边的长度必须相同,其次对角线长度要想通,一开始做的时候没有考虑到菱形的情况没有加上对角线相同的情况。对角线是一个正方形中最长的线段,一个正方形中有6个线段,而对角线的长度是最长的线段。计算出6个线段长度后先对6条线段长度排序。只需要判断前四条线段线段是否相同并且后两条线段也相同就可以构成一个正方形。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	
	private static double getDistance(int x1, int y1, int x2, int y2) {
		double dert_x = Math.pow((double)Math.abs(x2-x1), 2);
		double dert_y = Math.pow((double)Math.abs(y2-y1), 2);
		double result = Math.sqrt(dert_y + dert_x);
		
		return result;
	}
	
	private static boolean judge(double len1, double len2, double len3, double len4) {
		if(len1 == len2 && len1 == len3 && len1 == len4 
		&& len2 == len3 && len2 == len4 
		&& len3 == len4) {
			return true;
		}else {
			return false;
		}
	}
	
	private static boolean judge2(double len1, double len2) {
		return len1 == len2;
	}

	public static void main(String[] args) {
		int count;
		int i;
		int[][] x = new int[5][4];
		int[][] y = new int[5][4];
		
		Scanner sc = new Scanner(System.in);
		count = sc.nextInt();
		
		for(i = 0; i < count; i++) {
			x[i][0] = sc.nextInt();
			x[i][1] = sc.nextInt();
			x[i][2] = sc.nextInt();
			x[i][3] = sc.nextInt();
			y[i][0] = sc.nextInt();
			y[i][1] = sc.nextInt();
			y[i][2] = sc.nextInt();
			y[i][3] = sc.nextInt();
		}
		for(i = 0; i < count; i++) {
			double len1 = getDistance(x[i][0], y[i][0], x[i][1], y[i][1]);
			double len2 = getDistance(x[i][0], y[i][0], x[i][2], y[i][2]);
			double len3 = getDistance(x[i][1], y[i][1], x[i][3], y[i][3]);
			double len4 = getDistance(x[i][3], y[i][3], x[i][2], y[i][2]);
			double len5 = getDistance(x[i][3], y[i][3], x[i][0], y[i][0]);
			double len6 = getDistance(x[i][1], y[i][1], x[i][2], y[i][2]);
			double array[] = {len1, len2, len3, len4, len5, len6};
			Arrays.sort(array);
			boolean flag1 = judge(array[0], array[1], array[2], array[3]);
			boolean flag2 = judge2(array[4], array[5]);
			
			if(flag1 && flag2) {
				System.out.println("Yes");
			}else {
				System.out.println("No");
			}
		}
		
		
		sc.close();

	}

}

给出三个数a,b,c(a>b>c),范围是int的范围,统计2^a+2^b-2^c结果对应二进制中1的个数(微众银行)。

思路是最后统计二进制1的个数和a没有关系,分析2^b-2^c二进制有有多少个1,比如b=6,a=2,也就是100 0000 - 100=11 1100,结果中1的个数是b和c相差。


#include<stdio.h>

int a;
int b;
int c;

int main(void) {
	
	scanf("%d%d%d", &a, &b, &c);
	printf("%d",  1 + b - c);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/yvken_zh/article/details/80199899