小红书-2020测开(二)
- 224个叶子节点的完全二叉树, 最多有几个结点()
答案
448
题解
1、度为0的结点个数=度为2的结点个数+1,即n0=n2+1(其中n0表示度为0的结点个数,n2表示度为2的结点个数)。注 :二叉树的度代表某个结点的孩子或者说直接后继的个数。
2、完全二叉树中度为1的结点个数要么0个,要么1个。
3、二叉树结点个数n=n0+n1+n2
综合性质,结合题目有 n0=224,故224=n2+1,得n2=224-1=223。
当为度1的结点不存在时,结点总数为n=n0+n1+n2=224+0+223=447。
当为度1的结点存在时,结点总数为n=n0+n1+n2=224+1+223=448。
故最多为448个,选B
2. 散列表中解决冲突的方法有()
答案
再散列法 开放寻址法
题解
平方取中法和除数留余法属于哈希函数,另外还有直接定址法和随机数法,而解决哈希冲突的方法有,开放地址法(再哈希,二次探测、线性探测)和常用的链地址法
3. UDP报头中没有下面那些信息:()
答案
目的地址 窗口大小 序列号
题解
UDP报文段结构:源端口号,目的端口号,长度,检验和,应用数据
编程题
1. 笔记草稿 - 括号匹配/栈
薯队长写了一篇笔记草稿,请你帮忙输出最后内容。
1.输入字符包括,"(" , ")" 和 "<"和其他字符。
2.其他字符表示笔记内容。
3.()之间表示注释内容,任何字符都无效。 括号保证成对出现。
4."<"表示退格, 删去前面一个笔记内容字符。括号不受"<"影响 。
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); StringBuffer stringBuffer = new StringBuffer(); stringBuffer = new StringBuffer(scanner.nextLine()); List<Integer> k = new ArrayList<>(); //用一个列表来装括号的匹配 //遇见‘(’添加首次匹配位置进去 //遇见‘)’从最后一次‘(’匹配位置开始删除字符串 for(int i = 0; i < stringBuffer.length();){ if(stringBuffer.charAt(i)=='(') { k.add(i); i++; } else if(stringBuffer.charAt(i)=='<'&&k.size()==0) { stringBuffer.delete(i - 1, i + 1); i = i - 1; } else if(stringBuffer.charAt(i)==')') { stringBuffer.delete(k.get(k.size() - 1),i + 1); i = k.get(k.size() - 1); k.remove(k.size() - 1); } else i++; } System.out.println(stringBuffer); } }
2. 迷宫游戏 - DFS/BFS
薯队长最近在玩一个迷宫探索类游戏,迷宫是一个N*N的矩阵形状,其中会有一些障碍物禁止通过。这个迷宫还有一个特殊的设计,它的左右 边界以及上下边界是连通的,比如在(2,n)的位置继续往右走一格可以到(2,1), 在(1,2)的位置继续往上走一格可以到(n,2)。请问薯队长从起点位置S,最少走多少格才能到达迷宫的出口位置E。
输入描述:
第一行一个正整数N。 接下来N行。每行两个整数分别表示X 和 H X1 H1 X2 H2 … XN HN
输入限制: 对于70%的数据:
0<N<10^4
0<Xi<10^6
0<Hi<10^6
100%的数据:
0<N<10^6
0<Xi<10^6
0<Hi<10^6
输出描述:
一个整数,表示最多可以卖出的宝物数
输入
5
.#...
..#S.
.E###
.....
.....
输出
4
importjava.util.Scanner; importjava.io.File; importjava.util.Queue; importjava.util.LinkedList; classNode{ publicintx; publicinty; publicintlayer; publicNode(intx,inty,intlayer) { this.x = x; this.y = y; this.layer = layer; } } publicclassMain { publicstaticvoidmain(String[] args)throwsException{ //File file = new File("in.txt"); //Scanner in = new Scanner(file); Scanner in =newScanner(System.in); intn = in.nextInt(); in.nextLine(); char[][] board =newchar[n][n]; intstartX = -1;intstartY = -1; intendX = -1;intendY = -1; for(inti =0; i < n; i++) { String line = in.nextLine(); for(intj =0; j < n; j++) { board[i][j] = line.charAt(j); if(board[i][j] =='S') { startX = i; startY = j; }elseif(board[i][j] =='E') { endX = i; endY = j; } } } in.close(); if(startX == -1&& startY == -1) System.out.println("-1"); if(endX == -1&& endY == -1) System.out.println("-1"); Queue<Node> queue =newLinkedList<Node>(); intx = -1;inty = -1; queue.offer(newNode(startX, startY,0)); while(!queue.isEmpty()) { Node node = queue.poll(); //找到最后结果 if(node.x == endX && node.y == endY) { System.out.println(node.layer); return; } //四个方向 x = node.x +1; y = node.y; if(x == n) x =0; if(board[x][y] !='#') {queue.offer(newNode(x, y, node.layer +1)); board[x][y] ='#';} x = node.x -1; y = node.y; if(x == -1) x = n-1; if(board[x][y] !='#') {queue.offer(newNode(x, y, node.layer +1)); board[x][y] ='#';} x = node.x; y = node.y +1; if(y == n) y =0; if(board[x][y] !='#') {queue.offer(newNode(x, y, node.layer +1)); board[x][y] ='#';} x = node.x; y = node.y -1; if(y == -1) y = n-1; if(board[x][y] !='#') {queue.offer(newNode(x, y, node.layer +1)); board[x][y] ='#';} } System.out.println("-1"); } }
3. 倒卖战利品
在游戏中,击败魔物后,薯队长获得了N件宝物,接下来得把这些宝物卖给宝物回收员来赚点小钱。这个回收员有个坏毛病,每次卖给他一件宝 物后,之后他就看不上比这件宝物差的宝物了。在这个世界中,衡量宝物的好坏有两个维度,稀有度X和实用度H,回收员在回收一个宝物A 后,下一个宝物的稀有度和实用度都不能低于宝物A。那么薯队长如何制定售卖顺序,才能卖给回收员宝物总个数最多。
输入描述:
第一行一个正整数N。 接下来N行。每行两个整数分别表示X 和 H X1 H1 X2 H2 … XN HN
输入限制: 对于70%的数据:
0<N<10^4
0<Xi<10^6
0<Hi<10^6
100%的数据:
0<N<10^6
0<Xi<10^6
0<Hi<10^6
输出描述:
一个整数,表示最多可以卖出的宝物数
示例1
输入
4
3 2
1 1
1 3
1 2
输出
3
分析
思路 先对数组排序(sort函数会同时对两个维度排序,第一个维度相同时会比较第二个维度),然后在另一个维度上搜索最长上升子序列。
input: [[32],[11],[13],[12]]
sorted(input):[[11],[12],[13],[32]]
时间复杂度的限制:在找最长上升子序列时不能使用DP方法(O(N^2)),考虑通过二分查找来找到LIS。
LIS的二分查找算法:参考: leetcode 300.最长上升子序列
构造单调上升数组res,对原数组nums逐个遍历:
如果nums[i]>res[-1],说明满足上升条件,将其插入数组中;
否则,通过二分查找res数组中刚好比它大的值并进行替换。当完成多次替换后该数组的最大值会减小,从而能向res中添加一些原数组中较小的值。
计算数组的长度得到LIS的最大值。
注意二分搜索时的边界以及返回值选择
按照一个维度排序后按照另一个维度寻找最长增加子序列即可,这个是>=的比较简单一点,注意不能用O(n2),要二分查找优化 import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int[][] ans = new int[n][2]; for(int i=0;i<n;i++){ ans[i][0] = scanner.nextInt(); ans[i][1] = scanner.nextInt(); } Arrays.sort(ans,(a,b)->a[0]!=b[0]?a[0]-b[0]:a[1]-b[1]); int[] arr = new int[n]; for(int i=0;i<n;i++)arr[i] = ans[i][1]; System.out.println(LIS(arr)); } public static int LIS(int[] arr){ int[] dp = new int[arr.length]; int res = 0; for(int num:arr){ int l = 0,r = res; while (l<r){ int m = (l+r)/2; if(dp[m]<num)l = m+1; else r = m; } dp[l] = num; if(l==res)res++; } return res; } }