滴滴出行2017秋招笔试真题-编程题汇总_Java实现
注:有的题参考别人的思路,用我最容易理解的代码编的程序,所以可以不能最优的解法,后续我会进行更新,只是一个思路,我的笔记而已,所以不喜勿喷~~~
我会将具体将具体参考代码的博客放在后面,若有侵权,请告知我,我会立刻删除。
(1)连续最大和
解题思路:这个简单,就是定义一个sum,遍历数组,若是sum<0,说明前面的数组并不好,所以sum=temp[i], 否则,当前的值是可以补偿负数的,所以sum+=temp[i].
(2) 地下迷宫
回溯法
(3) 末尾0的个数
看n里面有多少个5
(4) 餐馆
解题思路:参考牛客网评论区
(5) 进制转换
(6) 数字和为sum的方法数
参考链接:https://blog.csdn.net/qq_43109561/article/details/90488445
习题及代码实现:
1. [编程题]连续最大和
时间限制:1秒
空间限制:32768K
一个数组有 N 个元素,求连续子数组的最大和。 例如:[-1,2,1],和最大的连续子数组为[2,1],其和为 3
输入描述:
输入为两行。 第一行一个整数n(1 <= n <= 100000),表示一共有n个元素 第二行为n个数,即每个元素,每个整数都在32位int范围内。以空格分隔。
输出描述:
所有连续子数组中和最大的值。
输入例子1:
3 -1 2 1
输出例子1:
3
代码实现:
import java.util.*;
public class Main{
public static void main(String [] args){
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int [] temp=new int[n];
for(int i=0;i0){
sum+=temp[i];
}else{
sum=temp[i];
}
max=Math.max(max,sum);
}
return max;
}
}
2. [编程题]地下迷宫
时间限制:1秒
空间限制:32768K
小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值P跳出这个地下迷宫。为了让问题简单,假设这是一个n*m的格子迷宫,迷宫每个位置为0或者1,0代表这个位置有障碍物,小青蛙达到不了这个位置;1代表小青蛙可以达到的位置。小青蛙初始在(0,0)位置,地下迷宫的出口在(0,m-1)(保证这两个位置都是1,并且保证一定有起点到终点可达的路径),小青蛙在迷宫中水平移动一个单位距离需要消耗1点体力值,向上爬一个单位距离需要消耗3个单位的体力值,向下移动不消耗体力值,当小青蛙的体力值等于0的时候还没有到达出口,小青蛙将无法逃离迷宫。现在需要你帮助小青蛙计算出能否用仅剩的体力值跳出迷宫(即达到(0,m-1)位置)。
输入描述:
输入包括n+1行:
第一行为三个整数n,m(3 <= m,n <= 10),P(1 <= P <= 100)
接下来的n行:
每行m个0或者1,以空格分隔
输出描述:
如果能逃离迷宫,则输出一行体力消耗最小的路径,输出格式见样例所示;如果不能逃离迷宫,则输出"Can not escape!"。 测试数据保证答案唯一
输入例子1:
4 4 10 1 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1
输出例子1:
[0,0],[1,0],[1,1],[2,1],[2,2],[2,3],[1,3],[0,3]
代码实现:
import java.util.*;
public class Main{
public static void main(String [] args){
Scanner in=new Scanner(System.in);
int n=Integer.parseInt(in.next());
int m=Integer.parseInt(in.next());
int p=Integer.parseInt(in.next());
int [][] temp=new int[n][m];
for(int i=0;i= 0)
res = str + "[0," + (m - 1) + "]";
else
res = "Can not escape!";
return;
}
// 从这一点往四个方向走:还没有走到头
if(row=0 && col>=0 && temp[row][col]==1&& !flag[row][col]) {
flag[row][col]=true;//往这一点走
str+="["+row+","+col+"],";
//水平向右走
getRes(temp,flag,row,n,col+1,m,str,p-1);
//向下走:不消耗能量
getRes(temp,flag,row+1,n,col,m,str,p);
//水平向左走
getRes(temp,flag,row,n,col-1,m,str,p-1);
//向上走
getRes(temp,flag,row-1,n,col,m,str,p-3);
}
}
}
3. [编程题]末尾0的个数
时间限制:1秒
空间限制:32768K
输入一个正整数n,求n!(即阶乘)末尾有多少个0? 比如: n = 10; n! = 3628800,所以答案为2
输入描述:
输入为一行,n(1 ≤ n ≤ 1000)
输出描述:
输出一个整数,即题目所求
输入例子1:
10
输出例子1:
2
代码实现:
/*
计算这些数中有多少个5
*/
import java.util.*;
public class Main{
public static void main(String [] args){
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int res=getRes(n);
System.out.println(res);
}
public static int getRes(int n){
int res=0;
while(n>=5){
n/=5;
res+=n;
}
return res;
}
}
4. [编程题]餐馆
时间限制:1秒
空间限制:65536K
某餐馆有n张桌子,每张桌子有一个参数:a 可容纳的最大人数; 有m批客人,每批客人有两个参数:b人数,c预计消费金额。 在不允许拼桌的情况下,请实现一个算法选择其中一部分客人,使得总预计消费金额最大
输入描述:
输入包括m+2行。 第一行两个整数n(1 <= n <= 50000),m(1 <= m <= 50000) 第二行为n个参数a,即每个桌子可容纳的最大人数,以空格分隔,范围均在32位int范围内。 接下来m行,每行两个参数b,c。分别表示第i批客人的人数和预计消费金额,以空格分隔,范围均在32位int范围内。
输出描述:
输出一个整数,表示最大的总预计消费金额
输入例子1:
3 5 2 4 2 1 3 3 5 3 7 5 9 1 10
输出例子1:
20
import java.util.*;
/*
基本思路就是:桌子序列升序排列 ,客人按照预定花钱多少降序排序,然后贪心法从钱多的客人开始招呼。
但是这题时间复杂度卡得太紧,在遍历能容得下第i批客人的时候需要二分查找去找否则超时
*/
public class Main {
public static void main(String [] args){
Scanner in=new Scanner(System.in);
int n=Integer.parseInt(in.next());
int m=Integer.parseInt(in.next());
int [] table=new int[n];
for(int i=0;i() {
@Override
public int compare(int[] o1, int[] o2) {
return o2[1]-o1[1];
}
});
//从桌子开始装人
long sum=0;
int index=0;//找桌子的位置
boolean [] flag=new boolean[n];//n个桌子,从第i个客人找桌子
for(int i=0;itable[n-1]) {
continue;//客人比桌子最大安排数大,招待不了了
}
index=findTable(temp[i][0],table);
while(index>1;
if(table[mid]>=target) {
end=mid-1;
}else {
start=mid+1;
}
}
return start;
}
}
5. [编程题]进制转换
时间限制:1秒
空间限制:32768K
给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数
输入描述:
输入为一行,M(32位整数)、N(2 ≤ N ≤ 16),以空格隔开。
输出描述:
为每个测试实例输出转换后的数,每个输出占一行。如果N大于9,则对应的数字规则参考16进制(比如,10用A表示,等等)
输入例子1:
7 2
输出例子1:
111
代码实现:
import java.util.*;
public class Main{
public static void main(String [] args){
Scanner in=new Scanner(System.in);
while(in.hasNext()){
String [] s=in.nextLine().split(" ");
int m=Integer.parseInt(s[0]);
int n=Integer.parseInt(s[1]);
int sign=0;
if(m<0){
sign=-1;
m=-m;
}
String res=getRes(m,n);
if(sign==-1){
System.out.println("-"+res);
}else{
System.out.println(res);
}
}
in.close();
}
public static String getRes(int m,int n){
StringBuffer sb=new StringBuffer();
//如果是二进制的
while(m!=0){
int ys=m%n;
if(ys>9){
//余数大于9的时候
char c=(char)((ys-10)+'A');
sb.append(c);
}else{
sb.append(ys);
}
m/=n;
}
return sb.reverse().toString();
}
}
6. [编程题]数字和为sum的方法数
时间限制:1秒
空间限制:32768K
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数Ai,以空格隔开。
输出描述:
输出所求的方案数
输入例子1:
5 15 5 5 10 2 3
输出例子1:
4
import java.util.*;
public class Main{
public static void main(String [] args){
Scanner in=new Scanner(System.in);
int n=Integer.parseInt(in.next());
int sum=Integer.parseInt(in.next());
int[] temp = new int[n+1];
for(int i=1; i<=n; i++){
temp[i] =Integer.parseInt(in.next()); //in.nextInt();
}
//System.out.println(Arrays.toString(temp));
long res=getRes(n,sum,temp);
System.out.println(res);
}
public static long getRes(int n,int sum,int [] temp){
//前i个人组成j的个数
//dp[i,j]表示前i个可以凑到j的个数
long [] [] dp=new long[n+1][sum+1];
//初始化
//前i个人组成j的个数为0;
for(int i=0;i<=n;i++) {
dp[i][0]=1;
}
for(int i=1; i<=n; i++){
for(int j=0; j<=sum; j++){
//等于拿了这个数据和没拿这个数据的方案总和,没拿时只需要看前i-1个数据组成j-p[i]的方案数
if(temp[i] <= j){
dp[i][j] = dp[i-1][j] +dp[i-1][j-temp[i]];
}else{//p[i]>j时只能选择不拿
dp[i][j] = dp[i-1][j];
}
}
}
return dp[n][sum];
}
}