滴滴2017秋招编程题

xiaoxiao2021-02-28  162

[编程题] 连续最大和

时间限制:1秒 空间限制:32768K 一个数组有 N 个元素,求连续子数组的最大和。 例如:[-1,2,1],和最大的连续子数组为[2,1],其和为 3 输入描述: 输入为两行。 第一行一个整数n(1 <= n <= 100000),表示一共有n个元素 第二行为n个数,即每个元素,每个整数都在32位int范围内。以空格分隔。 输出描述: 所有连续子数组中和最大的值。 输入例子1: 3 -1 2 1 输出例子1: 3

解析:

用f[i]表示以元素i结尾的子数组的最大元素和,则: f[i] = a[i] , i==0 或者 f[i-1] < 0 (前面的元素和小于0,则可以直接抛弃) f[i] = f[i-1] + a[i] , f[i-1] > 0 然后求出max(f[i])即可。

c++代码实现:

#include <iostream> using namespace std; long long maxSubSum(int *a,int n) { long long sum = 0; long long result = -2147483648; for(int i=0; i<n; i++){ if(sum<=0) sum = a[i]; else sum += a[i]; if(sum > result) result = sum; } return result; } int main() { int n; cin>>n; if(n<=0) return 0; int a[n]; for(int i=0; i<n; i++){ cin>>a[i]; } cout<<maxSubSum(a,n); return 0; }

[编程题] 餐馆

时间限制:1秒 空间限制:32768K 某餐馆有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

解析:

贪心算法。将客人信息按照:金额降序,人数升序进行排序。然后将桌子按容量进行升序排序。然后枚举每批客人查找当前最适合的桌子容量,采用二分查找。

C++代码实现:

#include <iostream> #include <algorithm> #include <set> using namespace std; typedef struct{ int num; int money; }Customer; unsigned long long maxIncoming(int n,int m,int *container,Customer* customer) { multiset<int> table(container,container+n); sort(customer,customer+m,[](const Customer &c1,const Customer& c2){ if(c1.money != c2.money) return c1.money > c2.money; return c1.num < c2.num; }); unsigned long long total = 0; for(int i=0; i<m; i++){ auto it = table.lower_bound(customer[i].num); if(it!=table.end()){ total += customer[i].money; table.erase(it); } } return total; } int main() { int n,m; cin>>n>>m; int container[n]; Customer customer[m]; for(int i=0; i<n; i++) cin>>container[i]; for(int i=0; i<m; i++) cin>>customer[i].num>>customer[i].money; cout<<maxIncoming(n,m,container,customer); return 0; }

[编程题] 地下迷宫

时间限制: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]

解析:

深度搜索。从起点开始,有四个方向可以走,每走一步,判断其是否到达出口且体力大于0,如果是,则表示找到一条路径,更新路径信息;如果不是出口,则依次探测4个方向。直至所有路径遍历完毕。代码有详细解释。

C++代码实现:

#include <iostream> #include <vector> using namespace std; typedef struct Point{ int row; int col; Point(int x,int y):row(x),col(y){} Point():row(0),col(0){} }Point; int direction[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; int cost[4] = {0,-1,-3,-1}; int maze[10][10]; int n,m,p; vector<Point> bestPath; vector<Point> curPath; int maxPower = 0x80000000; void printPath() { int i=0; for(; i<bestPath.size()-1; i++) cout<<"["<<bestPath[i].row<<","<<bestPath[i].col<<"],"; cout<<"["<<bestPath[i].row<<","<<bestPath[i].col<<"]"; } void findPath(int x,int y,int curPower) { //将当前节点加入路径中标记为visited curPath.push_back(Point(x,y)); maze[x][y] = 2; //visited //到达出口,找到一条路径 if(x==0 && y==m-1 && curPower>=0){ //找到一条路径 if(curPower > maxPower){ bestPath = curPath; maxPower = curPower; } curPath.pop_back(); //回退至上一步 maze[x][y] = 1; //还原 return; } //当前节点并非出口,且体力不为0,则往4个方向上继续探测 if(curPower>=0){ for(int i=0; i<4; i++){ int cx = x+direction[i][0]; int cy = y+direction[i][1]; int cp = curPower+cost[i]; if(cx>=0 && cx<=n && cy>=0 && cy<=m && cp>=0 && maze[cx][cy]==1) findPath(cx,cy,cp); } } curPath.pop_back(); //回退至上一步 maze[x][y] = 1; //还原 } int main() { cin>>n>>m>>p; for(int i=0; i<n; i++){ for(int j=0; j<m; j++) cin>>maze[i][j]; } findPath(0,0,p); if(maxPower>=0) printPath(); else cout<<"Can not escape!"; return 0; }

[编程题] 末尾0的个数

时间限制:1秒 空间限制:32768K 输入一个正整数n,求n!(即阶乘)末尾有多少个0? 比如: n = 10; n! = 3628800,所以答案为2 输入描述: 输入为一行,n(1 ≤ n ≤ 1000) 输出描述: 输出一个整数,即题目所求 输入例子1: 10 输出例子1: 2

解析

分析一下末尾0会在什么情况下出现? (1) 5(数字末尾位5)乘于一个偶数,结果肯定有0; (2)数字末尾就是0的,结果也有0; 第二条可以转变成5*x的形式,比如15=5*3,25=5*5 因此,计算n!结果中末尾0的个数,只需要找到[1-n] n个数中,因子5的个数。 注意:类似于25,可以拆分成5*5,需要注意。

C++代码实现:

#include <iostream> using namespace std; int endWithZero(int n) { if(n<5) return 0; int count = 0, i,j; for(i=5; i<=n; i+=5){ j = i; while(j%5==0){ count++; j /= 5; } } return count; } int main() { int n; cin>>n; if(n<1 || n>1000) return 0; cout<<endWithZero(n); return 0; }

[编程题] 进制转换

时间限制:1秒 空间限制:32768K 给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数 输入描述: 输入为一行,M(32位整数)、N(2 ≤ N ≤ 16),以空格隔开。 输出描述: 为每个测试实例输出转换后的数,每个输出占一行。如果N大于9,则对应的数字规则参考16进制(比如,10用A表示,等等) 输入例子1: 7 2 输出例子1: 111

解析:

(1)注意负数,需要转换成正数; (2)如果是-2147483648,转换位正数是214748648,超出了32位int范围,得用unsigned int或者long 。

c++代码实现:

#include <iostream> using namespace std; string factor = "0123456789ABCDEF"; void decToN(int num,int n) { if(num==0){ cout<<0; return; } bool flag = true; unsigned int m = 0; if(num<0){ m = ~num + 1; //注意-2147483648 ~ 2147483647 flag = false; } else m = num; int index = 31; char str[32]={0}; while(m!=0){ str[index--] = factor[m%n]; m /= n; } if(!flag) cout<<'-'; for(int i=index+1; i<32; i++) cout<<str[i]; } int main() { int m,n; cin>>m>>n; if(n<2 || n>16) return 0; decToN(m,n); return 0; }

[编程题] 数字和为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

解析:

(1)深度搜索。先对数组降序排序。然后用深度搜索。注意递归容易超时,需要用一个额外的数组来保存中间结果。 (2)动态规划。dp[i][j]代表前i个元素和为j的方案数量。 初始:dp[i][0] = 1(全部元素都不取,则和为0), dp[0][j] = 0; 推导方程: dp[i][j] = dp[i-1]j + dp[i-1][j-num[i]] (取第i个元素),if(j>=num[i]) dp[i][j] = dp[i-1][j], if (j < num[i])。

C++代码实现: 深度搜索

#include <iostream> #include <algorithm> #include <vector> using namespace std; int num[1000] = {0}; int sum = 0; int n = 0; vector<vector<long long>> dp; long long dfs(int last,int restSum) { if(restSum==0) return 1; if(dp[last][restSum]!=-1) return dp[last][restSum]; long long count = 0; for(int i=last; i<n; i++){ if(restSum >= num[i]) count += dfs(i+1,restSum-num[i]); } dp[last][restSum] = count; return count; } long long numberOfSum() { sort(num,num+n,greater<int>()); return dfs(0,sum); } int main() { cin>>n>>sum; dp.resize(n+1,vector<long long>(sum+1,-1)); for(int i=0; i<n; i++) cin>>num[i]; cout<<numberOfSum(); return 0; }

动态规划

#include <iostream> using namespace std; int num[1000] = {0}; int sum = 0; int n = 0; long long dp[1001][1001]={0}; long long numberOfSum() { for(int j=0; j<1001; j++) dp[0][j] = 0; for(int i=0; i<1001; i++) dp[i][0] = 1; //前i个元素和为0只有一种方案,就是全都不取 for(int i=1; i<=n; i++){ for(int j=0; j<=sum; j++){ if(j>=num[i-1]) dp[i][j] = dp[i-1][j] + dp[i-1][j-num[i-1]]; else dp[i][j] = dp[i-1][j]; } } return dp[n][sum]; } int main() { cin>>n>>sum; for(int i=0; i<n; i++) cin>>num[i]; cout<<numberOfSum(); return 0; }
转载请注明原文地址: https://www.6miu.com/read-25563.html

最新回复(0)