美团笔试记录
1 题 按字典序输出不重复的全排列
import java.util.ArrayList; import java.util.Arrays; import java.util.List; 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]; for (int i = 0; i < n; ++i) { arr[i] = sc.nextInt(); } Arrays.sort(arr); List<List<Integer>> ret = new ArrayList<>(); boolean[] vis = new boolean[n]; search(arr, ret, new ArrayList<>(), 0, vis); StringBuilder cache = new StringBuilder(); cache.append(ret.size()).append(" "); if (n > 0) { for (List<Integer> list : ret) { cache.append(list.get(0)); for (int i = 1; i < n; ++i) { cache.append(" ").append(list.get(i)); } cache.append(" "); } } System.out.println(cache); } private static void search(int[] arr, List<List<Integer>> ret, ArrayList<Integer> list, int idx, boolean[] vis) { if (idx == arr.length) { ret.add(new ArrayList<>(list)); return; } for (int i = 0; i < arr.length; ++i) { if (vis[i] || i > 0 && arr[i] == arr[i-1] && vis[i-1]) { continue; } vis[i] = true; list.add(arr[i]); search(arr, ret, list, idx + 1, vis); vis[i] = false; list.remove(list.size() - 1); } } }2 题 用堆记录同种字母出现的位置,方便快速查询。应该用TreeSet,由于我对集合使用的不那么熟,用了优先队列,也可以过。
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.next(); StringBuilder buf = new StringBuilder(str); int n = sc.nextInt(); Map<Character, PriorityQueue<Integer>> map = new HashMap<>(); for (char ch = 'a'; ch <= 'z'; ch++) { map.put(ch, new PriorityQueue<>()); } for (int i = 0; i < str.length(); ++i) { map.get(str.charAt(i)).add(i); } StringBuilder cache = new StringBuilder(); while (n-- > 0) { int opt = sc.nextInt(); if (opt == 1) { char ch = sc.next().charAt(0); map.get(ch).add(buf.length()); buf.append(ch); } else if (opt == 2) { int pos1 = sc.nextInt() - 1; char ch = buf.charAt(pos1); Integer[] arr = map.get(ch).toArray(new Integer[0]); int delta = Integer.MAX_VALUE; if (arr.length > 1) { int idx1 = Arrays.binarySearch(arr, pos1); if (idx1 >= 0) { if (idx1 != 0) { delta = Math.abs(arr[idx1 - 1] - pos1); } if (idx1 != arr.length - 1) { delta = Math.min(delta, Math.abs(arr[idx1 + 1] - pos1)); } } } cache.append(delta == Integer.MAX_VALUE ? -1: delta).append(" "); } } System.out.println(cache); } }3 括号相关的题
4 题 查询区间和,查询区间最大值。起初我写线段树提高区间最值查询的速度,但是回忆了好久,又好像写出了bug。于是先暴力交一下,没想到暴力就AC了,哎,这次笔试做得真惨
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]; for (int i = 0; i < n; ++i) { arr[i] = sc.nextInt(); } int[] preSum = new int[n+1]; for (int i = 1; i <= n; ++i) { preSum[i] = preSum[i-1] + arr[i-1]; // preSum[i] = arr[0..i) } int m = sc.nextInt(); StringBuilder cache = new StringBuilder(); // Tree tree = Tree.buildTree(0, arr.length - 1, arr); while(m-- > 0) { int opt = sc.nextInt(); int L = sc.nextInt() - 1; int R = sc.nextInt() - 1; if (opt == 1) { int sum = preSum[R+1] - preSum[L]; cache.append(sum).append(" "); } else if (opt == 2) { long res = 0; long sum = preSum[R+1] - preSum[L]; for (int j = L; j <= R; ++j) { res += (sum - arr[j]) * (sum - arr[j]); } cache.append(res).append(" "); } else if (opt == 3) { // int maxV = tree.query(L, R); int maxV = getMax(arr, L, R); cache.append(maxV).append(" "); } } System.out.println(cache); } private static int getMax(int[] arr, int l, int r) { int maxV = arr[l]; for (int i = l + 1;i <= r; ++i) { if (arr[i] > maxV) { maxV = arr[i]; } } return maxV; } } class Tree { int left; int right; int maxV; Tree lson; Tree rson; public Tree(int left, int right) { this.left = left; this.right = right; } static Tree buildTree(int left, int right, int[] arr) { Tree tree = new Tree(left, right); if (left > right) { tree.maxV = Integer.MIN_VALUE; return tree; } if (left == right) { tree.maxV = arr[left]; return tree; } int mid = left + right >> 1; tree.lson = buildTree(left, mid, arr); tree.rson = buildTree(mid +1, right, arr); tree.maxV = Math.max(tree.lson.maxV, tree.rson.maxV); return tree; } int query(int L, int R) { if (L <= left && right <= R) { return maxV; } int MaxV = Integer.MIN_VALUE; if (L <= lson.right) { maxV = lson.query(L, R); } if (R >= rson.left) { maxV = Math.max(maxV, rson.query(L, R)); } return maxV; } }5 题 后序遍历恢复树上节点的权重,再层次遍历输出权重。没时间了,哎