阿里笔试2023-3-15
太菜了,记录一下笔试题目,代码有更好解法欢迎分享。
1、满二叉子树的数量。
给定一颗二叉树,试求这课二叉树有多少个节点满足以该节点为根的子树是满二叉树?满二叉树指每一层都达到节点最大值。
第一行输入n表示节点数量,接下来n行第一个代表左儿子,第二个代表右儿子。
注意:由于没有说明1号节点就是根节点,因此需要寻找入度为0的节点作为根节点。
import java.util.*; public class Main { static int res = 0; public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int[][] nums = new int[n][2]; int root = -1; int[] inDegree = new int[n + 1]; for (int i = 0; i < n; i ++) { nums[i][0] = in.nextInt(); nums[i][1] = in.nextInt(); if (nums[i][0] != -1) { inDegree[nums[i][0]] ++; } if (nums[i][1] != -1) { inDegree[nums[i][1]] ++; } } for (int i = 1; i <= n; i ++) { if (inDegree[i] == 0) { root = i; break; } } new Main().isFullTree(nums, root); System.out.println(res); } public int height(int[][] nums, int root) { if (root == -1) { return 0; } return Math.max(height(nums, nums[root - 1][0]), height(nums, nums[root - 1][1])) + 1; } public boolean isFullTree(int[][] nums, int root) { if (root == -1) { return true; } boolean lb = isFullTree(nums, nums[root - 1][0]); boolean rb = isFullTree(nums, nums[root - 1][1]); if (lb && rb && height(nums, nums[root - 1][0]) == height(nums, nums[root - 1][1])) { res ++; return true; } else { return false; } } }
上述解法时间复杂度O(nlog(n)),空间复杂度o(log(n))。
另外,可以掌握根据数组进行二叉树建树
class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode() {} public TreeNode(int val) { this.val = val; } public TreeNode (TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } public static void main(String[] args) { List<TreeNode> nodeList = new ArrayList<>(); nodeList.add(null); for (int i = 1; i <= n; i ++) { nodeList.add(new TreeNode(i)); } for (int i = 0; i < n; i ++) { if (nums[i][0] == -1) { nodeList.get(i + 1).left = null; } else { nodeList.get(i + 1).left = nodeList.get(nums[i][0]); } if (nums[i][1] == -1) { nodeList.get(i + 1).right = null; } else { nodeList.get(i + 1).right = nodeList.get(nums[i][1]); } } }
2、三元组计数。
给定一个数组,计算有多少个三元组0<=i<j<k<n,且max(nums[i], nums[j], nums[k]) - min(nums[i], nums[j], nums[k]) = 1。
第一行输入n表示数组个数,第二行输入n个整数。
import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int[] nums = new int[n]; for (int i = 0; i < n; i++) { nums[i] = scanner.nextInt(); } Map<Integer, Long> map = new HashMap<>(); long res = 0; for (int i = 0; i < n; i ++) { map.put(nums[i], map.getOrDefault(nums[i], 0l) + 1); } for (Map.Entry<Integer, Long> entry : map.entrySet()) { long low = entry.getValue(); if (map.containsKey(entry.getKey() + 1)) { long high = map.get(entry.getKey() + 1); res += low * high * (high - 1) / 2; res += high * low * (low - 1) / 2; } } System.out.println(res); } }
上述解法时间复杂度O(n),需要空间复杂度O(n)。
3、乘2除2。
在n个元素的数组中选择k个元素,每个元素要么乘以2,要么除以2并向下取整,使得操作完后数组的极差尽可能小,并且输出极差。极差为最大值减去最小值。
第一行输入整数n和k。第二行输入n个整数表示数组。
import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int k = scanner.nextInt(); int[] nums = new int[n]; for (int i = 0; i < n; i++) { nums[i] = scanner.nextInt(); } Comparator<Integer> comparator = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }; Arrays.sort(nums); PriorityQueue<Integer> queueMin = new PriorityQueue<>(comparator); PriorityQueue<Integer> queueMid = new PriorityQueue<>(comparator); PriorityQueue<Integer> queueMax = new PriorityQueue<>(comparator); int minMin = Integer.MAX_VALUE, midMin = Integer.MAX_VALUE, maxMin = Integer.MAX_VALUE; for (int i = 0; i < k ; i ++) { minMin = Math.min(minMin, 2 * nums[i]); queueMin.add(2 * nums[i]); } for (int i = k; i < n; i ++) { midMin = Math.min(midMin, nums[i]); queueMid.add(nums[i]); } int res = Integer.MAX_VALUE; if (k == 0) { res = Math.min(res, queueMid.peek() - midMin); } else { res = Math.min(res, Math.max(queueMin.peek(), queueMid.peek()) - Math.min(minMin, midMin)); } for (int i = 0; i < k; i ++) { int tempMin = queueMin.poll(); queueMid.add(tempMin / 2); midMin = Math.min(midMin, tempMin / 2); int tempMid = queueMid.poll(); queueMax.add(tempMid / 2); maxMin = Math.min(maxMin, tempMid / 2); if (i == k - 1) { res = Math.min(res, Math.max(queueMid.peek(), queueMax.peek()) - Math.min(Math.min(minMin, midMin), maxMin)); } else { res = Math.min(res, Math.max(Math.max(queueMin.peek(), queueMid.peek()), queueMax.peek()) - Math.min(Math.min(minMin, midMin), maxMin)); } } System.out.println(res); } }
上述解法时间复杂度O(nlog(n)),空间复杂度O(n)。
#软件开发2023笔面经#