拼多多服务端研发工程师笔试(2021年7月25日下午三点场)
前言+说明
旺仔兄弟们,这个是拼多多应届生的笔试,总共四道算法题。下面由我一一道来,如果觉得博主分享的不错,希望能留下您的一键三连(评论+点赞+收藏),您的支持就是我的动力,您的三连对我特别重要。
注明:下述题目只用于学习交流所用,禁止用于商业销售。同时在题解方面也希望大家能提出宝贵建议,共同进步!
一、算法编程题
题目描述
给定N条线段,判断其中是否存在任意两条线段a和b,使得线段a完全包含在线段b之中。
例如:线段a = [1 , 3] 完全包含在b =[0 , 4] 之中。端点相同的线段也可以看作包含,例如a = [0 , 3] , b = [0 ,4],或者a = [1, 2],b = [0, 4],或者a = [1,2],b = [1,2]。
现在,请你帮助多多写一个程序完成上述之判定。
输入描述
第一行,一个整数N,表示线段的数量。(2 <= N <= 10,000)
之后N行,每行两个数字:Li 和 Ri ,分别表示第 i 个线段的两个端点。(0 <= Li <= Ri <= 10,000)
输出描述
共一行,一个字符串。
如果存在任意两条线段满足其中一条被另一条被另一条包含,则输出 " true " ,反之则输出 " false "。
(不包括引号,注意区分大小写)
示例1
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
4
1 3
4 5
7 10
13 18
输出
false
示例2
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
4
2 3
1 9
4 10
5 20
输出
true
参考代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[][] arr = new int[N][2];
for (int i=0; i<N; i++){
for (int j=0; j<2; j++){
arr[i][j] = sc.nextInt();
}
}
boolean ans = false;//用于存储结果
flag:for (int k1=0; k1<N; k1++){
for (int k2=k1+1; k2<N; k2++) {
ans = judgle(arr[k1], arr[k2]);
if (ans){
break flag;//如果ans为true直接跳出到flag(两个for循环)
}
}
}
System.out.println(ans);
}
public static boolean judgle(int[] a, int[] b){
if (a[0] >= b[0] && a[1] <= b[1]){
return true;
}
return false;
}
}
二、算法编程题
题目描述
多多鸡和多多鸭在玩一个纸牌游戏,名字叫做小猫钓鱼,游戏规则如下:
起初,多多鸡和多多鸭各有N张手牌,手牌的顺序是固定的,两人只能按照顺序出牌,多多鸡先出:
然后,多多鸡和多多鸭轮流在牌桌上以接龙的方式放置卡牌,即放置的卡牌按照先后顺序从左到右排成一行;
当某个人放置的一张卡牌的数字在桌牌上已经出现过时,他会把这两张以及两张之间的牌收走作为赢得的筹码,同时需要再放一张手牌接在牌尾;
如果手中已经无牌,则直接跳过,由对方放牌;
当两人手中都无牌时,游戏结束;
游戏结束时,若牌桌上还有剩余的牌,则多多鸡取走牌面为奇数的牌作为筹码,多多鸭取走牌面为偶数的牌作为筹码;
最后筹码数多的人获胜,两者筹码一样多则平局。
请问最后多多鸡和多多鸭各能获取多少筹码?
输入描述
共3行,
第一行,一个整数 N
第二行,N 个整数 a, …a…,用空格隔开,表示多多鸡的手牌数字
第三行,N 个整数 b, …b…,用空格隔开,表示多多鸭的手牌数字
输出描述
共一行,一个字符串。
如果存在任意两条线段满足其中一条被另一条被另一条包含,则输出 " true " ,反之则输出 " false "。
(不包括引号,注意区分大小写)
示例1
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
2
1 1
2 2
输出
3 1
示例2
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
4
1 2 3 4
5 6 7 8
输出
4 4
参考代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[][] arr = new int[2][N];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < N; j++) {
arr[i][j] = sc.nextInt();
}
}
//多多鸡手上的牌
List<Integer> chickenList = Arrays.stream(arr[0]).boxed().collect(Collectors.toList());
//多多鸭手上的牌
List<Integer> duckList = Arrays.stream(arr[1]).boxed().collect(Collectors.toList());
List<Integer> list = new ArrayList<Integer>();//用于存放桌面上的牌
int num = 0;//记录最后桌上的牌面数组
int[] ans = new int[2];//用于记录多多鸡和多多鸭的最终成绩。
//两者手中都无牌时,退出
while(!chickenList.isEmpty() || !duckList.isEmpty()){
//多多鸡先出
if (!chickenList.isEmpty()){
if (list.contains(chickenList.get(0))) {
list.add(chickenList.remove(0));
ans[0] += caculate(list);
}else if (!chickenList.isEmpty()){
list.add(chickenList.remove(0));
}
}
if(!duckList.isEmpty()){//多多鸭后出
if (list.contains(duckList.get(0))){
list.add(duckList.remove(0));
ans[1] += caculate(list);
}else if (!duckList.isEmpty()){
list.add(duckList.remove(0));
}
}
}
//多多鸡和多多鸭牌全部出完后,桌面上还有牌
while (!list.isEmpty()){
num = list.remove(0);
if (num%2 == 1){
ans[0]++;
}else{
ans[1]++;
}
}
System.out.println(Arrays.toString(ans));
}
public static int caculate(List<Integer> list){
int len = list.size();
int last = list.get(len-1);
while(list != null){
list.remove(list.size() - 1);
if (last == list.get(list.size()-1)){
list.remove(list.size()-1);
return len - list.size();
}
}
return 0;
}
}
三、算法编程题
题目描述
多多君最近在研究无限数字集合,其中一种生成无限数字集合的方式是:
1.初始状态集合中只有一个种子元素A。
2.对于集合中的每个元素X,有X + B也属于该集合。
3.对于集合中的每个元素X,有X * C也属于该集合。
多多君想知道,对于给定的参数A、B和C,数字Q是否属于该集合。
输入描述
第一行,一个整数T,表示测试用例的组数。(1 <= T <= 100)
对于每组测试用例,分别各一行,每行四个整数:A,B,C和Q,分别代表无限集合的参数和需要进行判断的数字。(1 <= A,B,C,Q <= 1,000,000,000)
输出描述
对于每组测试数据:
输出一行,若Q属于该无限集合则输出1,否则输出0。
示例1
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
3
1 2 3 5
2 3 2 10
3 3 3 7
输出
1
1
0
说明
第一组用例:5 = 1 * 3 + 2,属于该集合。
第二组用例:10 = (2 + 3) * 2,属于该集合。
第三组用例:集合中的元素从小到大分别为:3,6,9,12 … 均为3的倍数,故7不属于该集合。
参考代码
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[][] arr = new int[N][4];
for (int i=0; i<N; i++){
for (int j=0; j<4; j++){
arr[i][j] = sc.nextInt();
}
}
for (int[] row : arr){
if (conclude(row)){
System.out.println(1);
}else {
System.out.println(0);
}
}
}
public static boolean conclude(int[] row){
List<Integer> list = new ArrayList<Integer>();
list.add(row[0]);
int first = list.get(0);
while (!list.isEmpty()){
if (first > row[3]){
return false;
}else if(first == row[3]){
return true;
}
list.add(first + row[1]);
list.add(first * row[2]);
first = list.remove(0);
}
return false;
}
}
四、算法编程题
题目描述
多多最近在研究乘法,现在他拿到了一堆数字,他可以把这堆数字任意排列并组成一个乘法算式,他想知道怎么排列组合,能让最终乘出来的结果最大。
输入描述
共一行,10个整数,分别表示0到9的数量,保证每个数字的数量不超过100,并且总数量不小于2。
输出描述
共一行,一个整数,表示输出来的结果的最大值。
示例1
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
0 4 0 0 0 0 0 0 0 0
输出
121
说明
11 * 11 = 121
示例2
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
2 3 0 1 0 0 0 0 0 0
输出
3100 * 11 = 34100
备注
对于20%的测试数据,每个数字的数量不超过2。
参考代码(一)
//硬计算出来
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int[] arr = new int[10];
long[] ansArr = new long[2];//结果数值int型可能不够
long[] tempArr = new long[2];
long maxNum = 0L;//存储最大结果
for (int i=0; i<10 ; i++){
arr[i] = sc.nextInt();
}
for (int j=arr.length-1; j>0; j--){
if (arr[j] != 0){
tempArr = ansArr;
ansArr = merge(arr[j],j,tempArr);
}
}
if (arr[0] != 0){
ansArr[0] = mergeZero(ansArr[0],arr[0]);
}
maxNum = new Long(ansArr[0] * ansArr[1]);
System.out.println(maxNum);
}
private static long mergeZero(long ans, int num) {
for (int i=0; i<num;i++){
ans *= 10;
}
return ans;
}
public static long[] merge(int num, int index, long[] tempArr){
if (num%2 == 0){
for (int i=1; i<=num; i++){
if (i%2 == 1){
tempArr[0] = tempArr[0]*10 + index;
}else {
tempArr[1] = tempArr[1]*10 + index;
}
}
}else{
if (tempArr[0] <= tempArr[1]){
for (int i=1; i<=num; i++){
if (i%2 == 1){
tempArr[0] = tempArr[0]*10 + index;
}else {
tempArr[1] = tempArr[1]*10 + index;
}
}
}else {
for (int i=1; i<=num; i++){
if (i%2 == 1){
tempArr[1] = tempArr[1]*10 + index;
}else {
tempArr[0] = tempArr[0]*10 + index;
}
}
}
}
return tempArr;
}
}
参考思路(二)
可将上述tempArr[0]和tempArr[1]按List集合方式存储,List中的元素都是0~9的数。相乘的结果以List集合逆序形式存储,有进位时:将进位数值加到下一个数组元素中,依次类推进行数组元素添加。最后将结果List集合数字按顺序输出的拼接数即为正确结果。解决了结果长度限制。