9.1 拼多多寻梦计划笔试题复盘
刷题少,考得不好,痛定思痛,参考了评论区很多大佬的解答贴,复盘整理出来。
第1道
读入一个数列和N值,返回按优先级排序的N个数,满足 (1)所有偶数优先级大于奇数 (2)同为偶数或同为奇数时,数值大的优先级高
输入描述:
每个测试输入的测试用例,包含一个用半角逗号(,)分开的自然数数列和1个参数N,数列和参数N用半角分号(;)隔开这里保证N小于数列的元素个数(不超过100)。
输出描述:
在一行内输出N个满足题目条件的自然数,用逗号隔开
示例1
输入:
555503,772867,756893,339138,399447,40662,859037,628085,855723,974471,599631,636153,581541,174761,948135,411485,554033,858627,402833,546467,574367,360461,566480,755523,222921,164287,420256,40043,977167,543295,944841,917125,331763,188173,353275,175757,950417,284578,617621,546561,913416,258741,260569,630583,252845;10
输出:
913416,566480,420256,339138,284578,40662,977167,974471,950417,948135
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner; public class Main { public static void main(String args[]) { Scanner sc = new Scanner(System.in); String line = sc.next(); String[] split = line.split(";"); int N = Integer.valueOf(split[1]); String[] nums = split[0].split(","); List<Long> nums_1 = new ArrayList<>(); List<Long> nums_2 = new ArrayList<>(); for (int i = 0; i < nums.length; i++) { long t = Long.valueOf(nums[i]); if (t % 2 == 0) { nums_2.add(t); } else { nums_1.add(t); } } Collections.sort(nums_1, Collections.reverseOrder()); Collections.sort(nums_2, Collections.reverseOrder()); List<Long> res = new ArrayList<>(N); for (int i = 0; i < Math.min(nums_2.size(), N); i++) { res.add(nums_2.get(i)); } if (res.size() < N) { for (int i = res.size(), j = 0; i < N; i++, j++) { res.add(nums_1.get(j)); } } for (int i = 0; i < N; i++) { if (i == 0) System.out.print(res.get(i)); else System.out.print("," + res.get(i)); } } }
第2道
产品经理小梅喜欢和他的男朋友小白一块玩扑克游戏。每一局,小梅抽取N张扑克牌,自左向右依次排列在桌面上;小白也抽取M(8>=N>=M>=1)张扑克牌,自左向右依次排列在桌面上。 小梅需要进行N个回合,使用手中的扑克牌,组成一个新的扑克牌的序列每个回合,小梅有d、l、r三种策略 选择d时,小梅将最左边的扑克牌丢弃 选择l时,小梅将最左边的扑克牌取出,放到新的扑克牌序列的最左边 选择r时,小梅将最左边的扑克牌取出,放到的扑克牌序列的最右边 N个回合完成,新的扑克牌序列与小白的扑克牌完全样(只考虑数字,不考虑花色),则小梅胜出 小梅向程序员小岛提了一个需求,希望了解获胜的全部方法。简化起见扑克牌仅包合1-9。
输入描述:
首先,输入数字S,作为局数(1<=10)每一局,分别输入两行字符串,分别代表小梅的抽取的扑克牌(从左向右排列)和小白抽取到的扑克牌(从左向右排列)
输出描述:
对于每一局,在开始和结束,分别输出{和}输出获胜的方法,回合策略的结尾输出一个空格。若存在多个获胜方法,请按字典序的升序输出。
示例1
输入:
3 123 3 123 321 45 67
输出:
{ d d l d d r } { l l l r l l } { }
暴力搜索可破。
import java.util.*; public class Main { static List<String> res; static Queue<String> road; public static void main(String args[]) { Scanner sc = new Scanner(System.in); int S = sc.nextInt(); for (int i = 0; i < S; i++) { String nums1 = sc.next(); String nums2 = sc.next(); res = new ArrayList<>(); road = new ArrayDeque<>(); find(nums1, "", nums2); printResult(res); } } private static void find(String origin, String now, String target) { if (target.equals(now)) { if (origin.length() >= 0) { for (int i = 0; i < origin.length(); i++) { road.offer("d"); } } res.add(String.join(" ",road)); return; } if (origin == null || origin.length() == 0) { return; } String left = String.valueOf(origin.charAt(0)); String norigin = origin.substring(1); road.offer("d"); find(norigin, now, target); road.poll(); road.offer("l"); find(norigin, left + now, target); road.poll(); road.offer("r"); find(norigin, now + left, target); road.poll(); } private static void printResult(List<String> res) { System.out.println("{"); if (res == null || res.size() == 0) { System.out.println("}"); return; } else { Collections.sort(res, (o1, o2) -> o1.compareTo(o2)); for (int i = 0; i < res.size(); i++) { String s = res.get(i); System.out.println(String.join(" ", s)); } } System.out.println("}"); } }
第3道
扔n个般子,第i个骰子有可能投掷出Xi种等概率的不同的结果,数字从1到Xi。所有般子的结果的最大值将作为最终结果。求最终结果的期望。
输入描述:
第一行一个整数n,表示有n个骰子。(1<=n<=50) 第二行n个整数,表示每个骰子的结果数xi。(2<=Xi<=50)
输出描述:
输出最终结果的期望,保留两位小数
示例1
输入:
2 2 2
输出:
1.75
这道计算题的技巧是,如计算f(3),将f(2)、f(1)的概率也囊括了进来,从整体上再将先前计算的f(2)、f(1)减去。
import java.util.Arrays; import java.util.HashMap; import java.util.Scanner; public class Main { static HashMap<Integer, Long> map; static int n; static int[] a; static double[] p; public static void main(String args[]) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); a = new int[n]; for (int i = 0; i < n; i++) { a[i] = sc.nextInt(); } Arrays.sort(a); p = new double[a[a.length - 1] + 1]; int begin = 0; for (int max = 1; max <= a[a.length - 1]; max++) { while (a[begin] < max) begin ++; double p_max = 1.0; for (int i = begin; i < n; i++) { p_max *= max / (double)a[i]; } p_max -= Arrays.stream(p).sum(); p[max] = p_max; } double EX = 0; for (int X = 1; X <= a[a.length - 1]; X++) { EX += X * p[X]; } System.out.printf("%.2f",EX); } }
第4道
在一块长为n,宽为m的场地上,有n X m个1 X 1的单元格。每个单元格上的数字就是按照从1到n和1到m中的数的乘积。具体如下: n = 3, m = 3 1 2 3 2 4 6 3 6 9 给出一个查询的值K,求出按照这个方式列举的的数中第k大的值v例如上面的例子里,从大到小为(9,6,6,4,3,3,2,2,1) k=1,v=9 K=2,v=6 K=3,v=6 ... k=8,v=2 k=9,V=1
输入描述:
只有一行是3个数n,m,k表示场地的宽高和需要查询的k。使用空格隔开
输出描述:
给出第k大的数的值。
示例1
输入:
3 3 4
输出:
4
备注:
【数据范围】 100%的效据 1 <= n,m <= 40000 1 <= k <= n*m 30%的数据 1 <= n, m <= 1000
原是LeetCode改编,668. 乘法表中第k小的数
public class Main { public static void main(String args[]) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int k = sc.nextInt(); int low = 1, high = m * n; while (low < high) { int mid = (low + high) / 2; int cnt = 0; for (int i = 1; i <= n; i++) { cnt += (mid / i > m) ? 0 : m - mid / i; } if (cnt < k) high = mid; else low = mid + 1; } System.out.println(low); } }