华为 OD 机试总结
核心数据
编程语言:Java
总分:300 分(满分400分)
各题得分拆分:
第一题:100 分 ×90% = 90 分
第二题:100 分 ×100% = 100 分
第三题:200 分 ×55% = 110 分
做题情况
考试时有些紧张,部分API回忆耗时些许。
第二题为纯DFS题,脑子抽风了,解题思路卡顿较久。
第三题为抽象数据结构题,我做的时候题目图片无法显示QAQ,需自行绘制逻辑图。
字符串分割
题目描述
给定一个非空字符串S,其被N个‘-’分隔成N+1个子串,给定正整数K,要求除第一个子串外,其余的子串需先合并为一个整体,再按每K个字符组成新的子串,所有新子串之间用‘-’分隔。对于每个新组成的子串,需按以下规则转换大小写:
若子串中小写字母数量 > 大写字母数量:将所有大写字母转换为小写字母;
若子串中大写字母数量 > 小写字母数量:将所有小写字母转换为大写字母;
若大小写字母数量相等:不做转换。 最终将第一个子串与所有转换后的新子串用‘-’连接,输出结果。
输入格式
输入为两行,第一行为正整数K,第二行为非空字符串S。
输出格式
输出为转换后的字符串。
示例
示例1
输入
输出
示例2
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int k = Integer.parseInt(sc.nextLine()); String[] strings = sc.nextLine().split("-" ); String s = "" ; for (int i = 1 ; i < strings.length; i++) { s += strings[i]; } int index = 0 ; StringBuilder sb = new StringBuilder (strings[0 ]); while (s.length() - index > k) { sb.append("-" + check(s.substring(index, index + k))); index += k; } if (sb.length() - index > 0 ) { sb.append("-" + check(s.substring(index))); } System.out.println(sb.toString()); } } private static String check (String str) { int upperNum = 0 ; int lowerNum = 0 ; for (int i = 0 ; i < str.length(); i++) { char ch = str.charAt(i); if (ch >= 'a' && ch <= 'z' ) { lowerNum++; } else if (ch >= 'A' && ch <= 'Z' ) { upperNum++; } } if (lowerNum > upperNum) { return str.toLowerCase(); } else if (lowerNum < upperNum) { return str.toUpperCase(); } else { return str; } } }
组成最大数
题目描述
小组中每位成员都有一张卡片,卡片上是 6 位内的正整数。将所有成员的卡片数字连起来可以组成多种不同的数字,要求计算能组成的最大数字。
输入描述
输入为用 “,” 号分割的多个正整数字符串,无需考虑非数字异常情况,小组人数最多 25 人。
输出描述
输出组成的最大数字字符串。
示例
示例 1
输入
输出
示例 2
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String[] strings = sc.nextLine().split("," ); Arrays.sort(strings, (a, b) -> (b + a).compareTo(a + b)); StringBuilder sb = new StringBuilder (); for (String str : strings) { sb.append(str); } System.out.println(sb.toString()); } } }
统计射击比赛成绩
题目描述
给定一个射击比赛成绩单,包含多个选手若干次射击的成绩分数,请对每个选手按其最高三个分数之和进行降序排名,输出降序排名后的选手 id 序列。
输入描述
输入第一行,一个整数 N,表示该场比赛总共进行了 N 次射击,产生 N 个成绩分数(2<=N<=100)
输入第二行,一个长度为 N 整数序列,表示参与每次射击的选手 id(0<=id<=99)
输入第三行,一个长度为 N 整数序列,表示参与每次射击选手对应的成绩(0<= 成绩 <=100)
输出描述
符合题设条件的降序排名后的选手 ID 序列
示例
输入
1 2 3 31 3,3,7,4,4,4,4,7,7,3,5,5,5 53,80,68,24,39,76,66,16,100,55,53,80,55
输出
说明
该场射击比赛进行了 13 次,参赛的选手为 {3,4,5,7}
3 号选手成绩 53,80,55 最高三个成绩的和为 188
4 号选手成绩 24,39,76,66 最高三个成绩的和为 205
5 号选手成绩 53,80,55 最高三个成绩的和为 188
7 号选手成绩 68,16,100 最高三个成绩的和为 184
比较各个选手最高 3 个成绩的和,有 4 号 > 3 号 = 5 号 > 7 号,由于 3 号和 5 号成绩相等,且 id 5>3,所以输出 5,3,7,4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); List<Integer>ids = Arrays.stream(sc.nextLine().split("," )).map( Integer::parseInt).collect(Collectors.toList()); List<Integer> scores = Arrays.stream(sc.nextLine().split("," )).map( Integer::parseInt).collect(Collectors.toList()); Map<Integer, List<Integer>>id_scores = new HashMap <>(); for (int i = 0 ; i < n; i++) { Integer id = ids.get(i); Integer score = scores.get(i); List<Integer> list = id_scores.getOrDefault(id, new ArrayList <>()); list.add(score); id_scores.put(id, list); } StringBuilder sb = new StringBuilder (); id_scores.entrySet() .stream() .filter(x->x.getValue().size() >= 3 ) .sorted((a, b)-> { int asum = sum(a.getValue()); int bsum = sum(b.getValue()); if (asum == bsum) { return b.getKey() - a.getKey(); } else { return bsum - asum; } }) .map(Map.Entry::getKey) .forEach(x->sb.append(x).append("," )); System.out.println(sb.toString().substring(0 , sb.length() - 1 )); } } private static int sum (List<Integer>list) { list.sort(Integer::compareTo); int ans = 0 ; for (int i = list.size() - 1 ; i >= list.size() - 3 ; i--) { ans += list.get(i); } return ans; } }
字符串序列判定
题目描述
输入两个字符串 S 和 L,都只包含英文小写字母。S 长度 <=100,L 长度 <=500,000。判定 S 是否是 L 的有效子串,判定规则如下:
S 中的每个字符在 L 中都能找到(可以不连续),且 S 在L中字符的前后顺序与 S 中顺序要保持一致。
(例如,S=”ace” 是 L=”abcde” 的一个子序列且有效字符是 a、c、e,而”aec” 不是有效子序列,且有效字符只有 a、e)
输入描述
输入两个字符串 S 和 L,都只包含英文小写字母。S 长度 <=100,L 长度 <=500,000。先输入 S,再输入 L,每个字符串占一行。
输出描述
S 串最后一个有效字符在 L 中的位置。(首位从 0 开始计算,无有效字符返回 - 1)
示例
示例 1
输入
输出
示例 2
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String S = sc.nextLine(); String L = sc.nextLine(); int j = 0 ; int ans = -1 ; for (int i = 0 ; i < L.length(); i++) { char lch = L.charAt(i); char sch = S.charAt(j); if (lch == sch) { j++; } if (j == S.length()) { ans = i; break ; } } System.out.println(ans); } } }
数据分类
题目描述
对一个数据 a 进行分类,分类方法为:此数据 a(四个字节大小)的四个字节相加对一个给定的值 b 取模,如果得到的结果小于一个给定的值 c,则数据 a 为有效类型,其类型为取模的值;如果得到的结果大于或者等于 c,则数据 a 为无效类型。
例如:
一个数据 a=0x01010101,b=3,按照分类方法计算 (0x01+0x01+0x01+0x01)%3=1
如果 c=2,则此 a 为有效类型,其类型为 1
如果 c=1,则此 a 为无效类型
一个数据 a=0x01010103,b=3,按照分类方法计算 (0x01+0x01+0x01+0x03)%3=0
如果 c=2,则此 a 为有效类型,其类型为 0
如果 c=0,则此 a 为无效类型
输入描述
输入 12 个数据,用空格分隔:
第一个数据为 c
第二个数据为 b
剩余 10 个数据为需要分类的数据
输出描述
输出最多数据的有效类型有多少个数据
示例
示例 1
输入
1 3 4 256 257 258 259 260 261 262 263 264 265
输出
说明
10 个数据 4 个字节相加后的结果分别为 1 2 3 4 5 6 7 8 9 10
故对 4 取模的结果为 1 2 3 0 1 2 3 0 1 2
c 为 3,所以 0、1、2 都是有效类型
类型为 1 和 2 的有 3 个数据,类型为 0 的只有 2 个数据,故输出 3
示例 2
输入
1 1 4 256 257 258 259 260 261 262 263 264 265
输出
说明
10 个数据 4 个字节相加后的结果分别为 1 2 3 4 5 6 7 8 9 10
故对 4 取模的结果为 1 2 3 0 1 2 3 0 1 2
c 为 1,所以只有 0 是有效类型,类型为 0 的有 2 个数据,故输出 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String []strings = sc.nextLine().split(" " ); int c = Integer.parseInt(strings[0 ]); int b = Integer.parseInt(strings[1 ]); Map<Integer, Integer>count = new HashMap <>(); for (int i = 2 ; i < strings.length; i++) { int x = Integer.parseInt(strings[i]); int sum = sum(x); sum %= b; if (sum < c) { count.put(sum, count.getOrDefault(sum, 0 ) + 1 ); } } int ans = 0 ; for (int x : count.values()) { ans = Math.max(ans, x); } System.out.println(ans); } } private static int sum (int x) { int byte1 = (x >> 24 ) & 0xFF ; int byte2 = (x >> 16 ) & 0xFF ; int byte3 = (x >> 8 ) & 0xFF ; int byte4 = x & 0xFF ; return byte1 + byte2 + byte3 + byte4; } }
5键键盘的输出
题目描述
有一个特殊的 5 键键盘,上面有 a,ctrl-c,ctrl-x,ctrl-v,ctrl-a 五个键,功能如下:
a 键:在屏幕上输出一个字母 a;
ctrl-c(对应数字 2):将当前选择的字母复制到剪贴板;
ctrl-x(对应数字 3):将当前选择的字母复制到剪贴板,并清空选择的字母;
ctrl-v(对应数字 4):将当前剪贴板里的字母输出到屏幕;
ctrl-a(对应数字 5):选择当前屏幕上的所有字母。
注意事项
剪贴板初始为空,新的内容被复制到剪贴板时会覆盖原来的内容;
当屏幕上没有字母时,ctrl-a 无效;
当没有选择字母时,ctrl-c 和 ctrl-x 无效;
当有字母被选择时,a 和 ctrl-v 这两个有输出功能的键会先清空选择的字母,再进行输出。
输入描述
输入为一行,为简化解析,用数字 1-5 代表五个键的输入,数字用空格分隔:
1:a 键
2:ctrl-c
3:ctrl-x
4:ctrl-v
5:ctrl-a
输出描述
输出一个数字,为最终屏幕上字母的数量。
示例
示例 1
输入
输出
说明 连续键入 3 个 a,故屏幕上字母的长度为 3。
示例 2
输入
输出
说明
输入两个 a 后 ctrl-a 选择这两个 a,再输入 a 时选择的两个 a 先被清空,所以此时屏幕只有一个 a,后续的 ctrl-a,ctrl-c 选择并复制了这一个 a,最后两个 ctrl-v 在屏幕上输出两个 a,故屏幕上字母的长度为 2(第一个 ctrl-v 清空了屏幕上的那个 a)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String [] strings = sc.nextLine().split(" " ); String screen = "" ; String temp = "" ; boolean selected = false ; for (int i = 0 ; i < strings.length; i++) { int x = Integer.parseInt(strings[i]); if (x == 1 ) { if (selected) { screen = "a" ; selected = false ; } else { screen += "a" ; } } else if (x == 2 ) { if (selected) { temp = screen; } } else if (x == 3 ) { if (selected) { temp = screen; screen = "" ; selected = false ; } } else if (x == 4 ) { if (selected) { screen = temp; selected = false ; } else { screen += temp; } } else if (x == 5 ) { if (!screen.equals("" )) { selected = true ; } } } System.out.println(screen.length()); } } }
检查是否存在满足条件的数字组合
题目描述
给定一个正整数数组,检查数组中是否存在满足规则的数组组合。规则:A = B + 2×C。要求数组中的每个成员只能在结果算式中使用一次(如数组成员为 [0,0,1,5],算式 0=0+2×0 不允许,因为使用了 3 个 0)。
输入描述
第一行输入数组的元素个数;
第二行输出所有数组元素,用空格隔开。
输出描述
如果存在满足要求的数,在同一行里依次输出规则里 A、B、C 的取值,用空格隔开;
如果不存在,输出 0。
示例
示例 1
输入
输出
说明
7 = 3 + 2×2,数组中每个元素仅使用一次。
备注
数组长度在 3~100 之间;
数组成员为 0~65535;
数组成员可以重复,但每个成员只能在结果算式中使用一次;
用例保证每组数字里最多只有一组符合要求的解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String []strings = sc.nextLine().split(" " ); int n = Integer.parseInt(strings[0 ]); int []arr = new int [n]; for (int i = 1 ; i <= n; i++) { arr[i - 1 ] = Integer.parseInt(strings[i]); } boolean ans = false ; Arrays.sort(arr); for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { for (int k = 0 ; k < n; k++) { if (arr[k] == arr[j] + arr[i] * 2 && i != j && j != k && i != k) { ans = true ; System.out.println(arr[k] + " " + arr[j] + " " + arr[i]); } } } } if (!ans) { System.out.println(0 ); } } } }
数组拼接
题目描述
现在有多组整数数组,需要将它们合并成一个新的数组。合并规则:从每个数组里按顺序取出固定长度的内容合并到新的数组中,取完的内容会删除掉;如果该行不足固定长度或者已经为空,则直接取出剩余部分的内容放到新的数组中,继续下一行。
输入描述
第一行是每次读取的固定长度,0 < 长度 < 10;
第二行是整数数组的数目,0 < 数目 < 1000;
第 3-n 行是需要合并的数组,不同的数组用回车换行分隔,数组内部用逗号分隔,最大不超过 100 个元素。
输出描述
输出一个新的数组,用逗号分隔。
示例
示例 1
输入
1 2 3 4 3 2 2,5,6,7,9,5,7 1,7,4,3,4
输出
1 2,5,6,1,7,4,7,9,5,3,4,7
说明
获得长度 3 和数组数目 2;
先遍历第一行,获得 2,5,6;
再遍历第二行,获得 1,7,4;
再循环回到第一行,获得 7,9,5;
再遍历第二行,获得 3,4;
再回到第一行,获得 7,按顺序拼接成最终结果。
示例 2
输入
1 2 3 4 5 4 3 1,2,3,4,5,6 1,2,3 1,2,3,4
输出
1 1,2,3,4,1,2,3,1,2,3,4,5,6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int len = Integer.parseInt(sc.nextLine()); int cnt = Integer.parseInt(sc.nextLine()); List<String> list = new ArrayList <>(); for (int i = 1 ; i <= cnt; i++) { list.add(sc.nextLine()); } Map<Integer, Queue<Integer>>map = new HashMap <>(); for (int i = 0 ; i < list.size(); i++) { String []strings = list.get(i).split("," ); Queue<Integer> queue = new ArrayDeque <>(); for (String str : strings) { queue.offer(Integer.parseInt(str)); } map.put(i, queue); } int num = 0 ; List<Integer>ans = new ArrayList <>(); while (!map.isEmpty()) { if (map.containsKey(num)) { for (int i = 0 ; i < len; i++) { if (map.get(num).isEmpty()) { map.remove(num); break ; } ans.add(map.get(num).poll()); } } num++; num %= list.size(); } System.out.println(ans.toString().substring(1 , ans.toString().length() - 1 )); } } }
数列描述
题目描述
有一个数列 A [n],从 A [0] 开始每一项都是一个数字字符串,数列中 A [n+1] 是对 A [n] 的描述,生成规则如下:
A [0] = 1(初始项)
A [1] = 11:含义是 A [0] 由 “1 个 1” 组成,即从左到右连续出现 1 次 1
A [2] = 21:含义是 A [1] 由 “2 个 1” 组成,即从左到右连续出现 2 次 1
A [3] = 1211:含义是 A [2] 由 “1 个 2、1 个 1” 组成,即从左到右先连续出现 1 次 2,再连续出现 1 次 1
A [4] = 111221:含义是 A [3] 由 “1 个 1、1 个 2、2 个 1” 组成,即从左到右先连续出现 1 次 1,再连续出现 1 次 2,最后连续出现 2 次 1
给定整数 n(0<=n<=59),输出数列的第 n 项结果。
输入描述
输入一个整数 n,表示数列的第 n 项(0<=n<=59)。
输出描述
输出数列第 n 项的字符串内容。
示例
示例 1
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); List<String>list = new ArrayList <>(); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); list.add("1" ); for (int i = 1 ; i <= n; i++) { String str = list.get(i - 1 ); String str1 = process(str); list.add(str1); } System.out.println(list.get(n)); } } private static String process (String str) { int len = str.length(); int i = 0 ; int cnt = 0 ; char ch; StringBuilder sb = new StringBuilder (); while (i < len) { ch = str.charAt(i); while (str.charAt(i) == ch && i < len) { cnt++; i++; if (i >= len) { break ; } } sb.append(cnt).append(ch); cnt = 0 ; } return sb.toString(); } }
考勤信息
题目描述
公司用一个字符串来表示员工的出勤信息:
absent:缺勤
late:迟到
leaveearly:早退
present:正常上班
现需根据员工出勤信息,判断本次是否能获得出勤奖,能获得出勤奖的条件如下:
缺勤不超过一次;
没有连续的迟到 / 早退;
任意连续 7 次考勤,缺勤 / 迟到 / 早退不超过 3 次。
输入描述
第一行输入一个整数 n,表示有多少个员工;后面 n 行,每一行输入若干个字符串(用空格分隔),表示第 i 名员工的出勤信息。
输出描述
输出 n 行,每一行表示这名员工能否获得出勤奖,如果可以,则输出 “true”,否则输出 “false”。
示例
示例 1
输入
1 2 3 2 present present absent present present leaveearly present absent
输出
示例 2
输入
1 2 3 2 present present present
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 import java.util.*;import java.util.stream.Collectors;public class Main { static Map<String, Integer>map = new HashMap <>(); static { map.put("absent" , 0 ); map.put("late" , 1 ); map.put("leaveearly" , 1 ); map.put("present" , 2 ); } public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); StringBuilder ans = new StringBuilder (); for (int i = 1 ; i <= n; i++) { String str = sc.nextLine(); ans.append(judge(str) + " " ); } System.out.println(ans.toString()); } } private static boolean judge (String str) { String []strings = str.split(" " ); StringBuilder sb = new StringBuilder (); for (String str1 : strings) { sb.append(map.get(str1)); } String s = sb.toString(); int absentCnt = 0 ; int len = s.length(); for (int i = 0 ; i < len; i++) { char ch = s.charAt(i); if (ch == '0' ) { absentCnt++; if (absentCnt > 1 ) { return false ; } } else if (ch == '1' ) { if (s.charAt(i + 1 ) == '1' && i + 1 < len) { return false ; } } if (i >= 6 ) { int badCnt = 0 ; for (int j = i; j >= i - 6 ; j--) { if (s.charAt(j) != '2' ) { badCnt++; } } if (badCnt > 3 ) { return false ; } } } return true ; } }
按单词下标区间翻转文章内容
题目描述
输入一个英文文章片段,翻转指定区间的单词顺序,标点符号和普通字母一样处理。
例如输入字符串 “I am a developer.”,区间 [0,3] 则输出 “developer. a am I”。
输入描述
使用换行隔开三个参数:
第一个参数为英文文章内容即英文字符串;
第二个参数为反转起始单词下标,下标从 0 开始;
第三个参数为结束单词下标。
输出描述
反转后的英文文章片段,所有单词之间以一个半角空格分割进行输出。
示例
示例 1
输入
输出
示例 2
输入
输出
说明
输入字符串可以在前面或者后面包含多余的空格,但是反转后的不能包含多余空格。
示例 3
输入
输出
说明
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
示例 4
输入
输出
说明
指定反转区间只有一个单词,或无有效单词则统一输出原字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String []strings = sc.nextLine().split(" " ); int start = Integer.parseInt(sc.nextLine()); int end = Integer.parseInt(sc.nextLine()); System.out.println(solve(strings, start, end)); } } private static String solve (String [] strings, int start, int end) { StringBuilder sb = new StringBuilder (); int n = strings.length; end = Math.min(end, n - 1 ); if (start > n - 1 || (end - start + 1 ) == 1 ) { for (int i = 0 ; i < n - 1 ; i++) { sb.append(strings[i]).append(" " ); } sb.append(strings[n - 1 ]); return sb.toString(); } int i = start, j = end; while (i < j) { String temp = strings[i]; strings[i] = strings[j]; strings[j] = temp; i++; j--; } for (int k = 0 ; k < n - 1 ; k++) { sb.append(strings[k]).append(" " ); } sb.append(strings[n - 1 ]); return sb.toString(); } }
最大括号深度
题目描述
现有一字符串仅由 ‘(‘,’)’,‘{‘,’}’,’[‘,’]’六种括号组成。若字符串满足以下条件之一,则为无效字符串:
①任一类型的左右括号数量不相等;
②存在未按正确顺序(先左后右)闭合的括号。
输出括号的最大嵌套深度,若字符串无效则输出 0。
备注 :0≤字符串长度≤100000
输入描述
一个只包括 ‘(‘,’)’,‘{‘,’}’,’[‘,’]’的字符串
输出描述
一个整数,最大的括号深度
示例
示例 1
输入
输出
说明
有效字符串,最大嵌套深度为 1
示例 2
输入
输出
说明
有效字符串,最大嵌套深度为 3
示例 3
输入
输出
说明
无效字符串,有两种类型的左右括号数量不相等
示例 4
输入
输出
说明
无效字符串,存在未按正确顺序闭合的括号
示例 5
输入
输出
说明
无效字符串,存在未按正确顺序闭合的括号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String str = sc.nextLine(); System.out.println(solve(str)); } } private static int solve (String str) { int ans = 0 ; Stack<Character> stack = new Stack <>(); for (int i = 0 ; i < str.length(); i++) { char ch = str.charAt(i); if (stack.isEmpty()) { if (!(ch == '(' || ch == '[' || ch == '{' )) { ans = 0 ; break ; } stack.push(ch); ans = Math.max(ans, stack.size()); } else if (ch == '(' || ch == '[' || ch == '{' ) { stack.push(ch); ans = Math.max(ans, stack.size()); } else { char ch1 = stack.peek(); if ((ch1 == '(' && ch != ')' ) || (ch1 == '[' && ch != ']' ) || (ch1 == '{' && ch != '}' )) { ans = 0 ; break ; } stack.pop(); } } return ans; } }
字符串加密
题目描述
给你一串未加密的字符串 str,通过对字符串的每一个字母进行改变来实现加密,加密规则如下:
对字符串的每一个字母 str [i] 偏移特定数组元素 a [i] 的量;
偏移数组 a 的初始值:a [0]=1,a [1]=2,a [2]=4;
当 i>=3 时,数组元素 a [i] = a [i-1] + a [i-2] + a [i-3]。
例如:原文 abcde 加密后 bdgkr,其中偏移量分别是 1,2,4,7,13。
输入描述
第一行为一个整数 n(1<=n<=1000),表示有 n 组测试数据;
每组数据包含一行,为原文 str(只含有小写字母,0 < 长度 <=50)。
输出描述
每组测试数据输出一行,表示字符串的密文。
示例
示例 1
输入
输出
说明
第一个字符 x 偏移量是 1,即为 y,第二个字符 y 偏移量是 2,即为 a。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int []a = new int [100 ]; a[0 ] = 1 ; a[1 ] = 2 ; a[2 ] = 4 ; for (int i = 3 ; i < 50 ; i++) { a[i] = (a[i - 1 ] + a[i - 2 ] + a[i - 3 ]) % 26 ; } int n = Integer.parseInt(sc.nextLine()); for (int i = 0 ; i < n; i++) { String str = sc.nextLine(); System.out.println(solve(str, a)); } } } private static String solve (String str, int []a) { StringBuilder sb = new StringBuilder (); for (int i = 0 ; i < str.length(); i++) { char ch = str.charAt(i); for (int j = 0 ; j < a[i]; j++) { ch += 1 ; if (ch > 'z' ) { ch = 'a' ; } } sb.append((char )ch); } return sb.toString(); } }
整数对最小和
题目描述
给定两个整数数组 array1、array2,数组元素按升序排列。假设从 array1、array2 中分别取出一个元素可构成一对元素,现在需要取出 k 对元素,并对取出的所有元素求和,计算和的最小值。
注意 :两对元素如果对应于 array1、array2 中的两个下标均相同,则视为同一对元素。
输入描述
输入两行数组 array1、array2,每行首个数字为数组大小 size (0 < size <= 100);
0 < array1 [i] <= 1000;
0 < array2 [i] <= 1000;
接下来一行为正整数 k(0 < k <= array1.size () * array2.size ())。
输出描述
满足要求的最小和
示例
示例 1
输入
输出
说明
用例中,需要取 2 对元素
取第一个数组第 0 个元素与第二个数组第 0 个元素组成 1 对元素 [1,1];
取第一个数组第 1 个元素与第二个数组第 0 个元素组成 1 对元素 [1,1];
求和为 1+1+1+1=4,为满足要求的最小和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int []arr1 = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int []arr2 = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int k = Integer.parseInt(sc.nextLine()); List<Integer>list = new ArrayList <>(); for (int i = 0 ; i < arr1.length; i++) { for (int j = 0 ; j < arr2.length; j++) { list.add(arr1[i] + arr2[j]); } } list.sort(null ); int ans = 0 ; for (int i = 0 ; i < k; i++) { ans += list.get(i); } System.out.println(ans); } } }
求字符串中所有整数的最小和
题目描述
输入字符串 s,输出 s 中包含所有整数的最小和,规则如下:
字符串 s 只包含 a~z、A~Z、+、-;
合法的整数包括正整数(一个或者多个 0-9 组成,如:0、2、3、002、102);
负整数(负号开头,数字部分由一个或者多个 0-9 组成,如 - 2、-012、-23、-00023)。
输入描述
包含数字的字符串
输出描述
所有整数的最小和
示例
示例 1
输入
输出
说明
1+2+3+4=10
示例 2
输入
输出
说明
1+2-34=-31
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String str = sc.nextLine(); int i = 0 ; int n = str.length(); int ans = 0 ; while (i < n) { char ch = str.charAt(i); if (ch == '-' ) { i++; int x = 0 ; while (str.charAt(i) >= '0' && str.charAt(i) <= '9' && i < n) { x = x * 10 + (str.charAt(i) - '0' ); i++; if (i >= n) { break ; } } ans -= x; continue ; } else if (ch >= '0' && ch <= '9' ) { ans += ch - '0' ; } i++; } System.out.println(ans); } } }
两数之和绝对值最小
题目描述
给定一个从小到大的有序整数序列(存在正整数和负整数)数组 nums,请你在该数组中找出两个数,其和的绝对值 (|nums [x]+nums [y]|) 为最小值,并返回这个绝对值。每种输入只会对应一个答案,且数组中同一个元素不能使用两遍。
输入描述
一个通过空格分割的有序整数序列字符串,最多 1000 个整数,且整数数值范围是 - 65535~65535。
输出描述
两数之和绝对值最小值
示例
示例 1
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int [] arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int ans = Integer.MAX_VALUE; for (int i = 0 ; i < arr.length; i++) { for (int j = i + 1 ; j < arr.length; j++) { ans = Math.min(ans, Math.abs(arr[i] + arr[j])); } } System.out.println(ans); } } }
非严格递增连续数字序列
题目描述
输入一个字符串仅包含大小写字母和数字,求字符串中包含的最长的非严格递增连续数字序列的长度(比如 12234 属于非严格递增连续数字序列)。
输入描述
输入一个字符串仅包含大小写字母和数字,输入的字符串最大不超过 255 个字符。
输出描述
最长的非严格递增连续数字序列的长度
示例
示例 1
输入
输出
说明
2234 为最长的非严格递增连续数字序列,所以长度为 4
测试用例 1
输入
1 aaaaaa44ko543j123j7345677781
输出
说明
34567778 为最长的非严格递增连续数字序列,长度为 8
测试用例 2
输入
1 aaaaa34567778a44ko543j123j71
输出
说明
34567778 为最长的非严格递增连续数字序列,长度为 8
测试用例 3
输入
1 345678a44ko543j123j7134567778aa
输出
说明
134567778 为最长的非严格递增连续数字序列,长度为 9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String str = sc.nextLine(); int ans = 0 ; int len = 0 ; char pre = '0' ; for (int i = 0 ; i < str.length(); i++) { char ch = str.charAt(i); if (ch >= pre && ch <= '9' ) { len++; pre = ch; ans = Math.max(ans, len); } else if (ch >= '0' && ch <= '9' ) { len = 1 ; pre = ch; } else { len = 0 ; pre = '0' ; } } System.out.println(ans); } } }
分积木
题目描述
Solo 和 koko 是两兄弟,妈妈给了他们一大堆积木,每块积木上都有自己的重量。现在他们想要将这些积木分成两堆:
哥哥 Solo 负责分配,弟弟 koko 要求两个人获得的积木总重量 “相等”(根据 Koko 的逻辑),个数可以不同,不然就会哭;
Koko 的加法逻辑:先将两个数转成二进制再进行加法,且总会忘记进位(每个进位都忘记)。例如 25(11001)加 11(01011)时,koko 得到的计算结果是 18(10010)。
Solo 想要尽可能使自己得到的积木总重量最大,且不让 koko 哭。
输入描述
第一行是一个整数 N (2≤ N ≤100),表示有多少块积木;
第二行为空格分开的 N 个整数 Ci (1 ≤ Ci ≤ 1000),表示第 i 块积木的重量。
输出描述
如果能让 koko 不哭,输出 Solo 所能获得积木的最大总重量;否则输出 “-1”。
示例
示例 1
输入
输出
说明
Solo 能获得重量为 5 和 6 的两块积木,5 转换成二进制是 101,6 的二进制是 110,按照 koko 的计算方法(忘记进位),结果为 3(二进制 011)。koko 获得重量为 3 的积木,而 solo 获得重量为 11(十进制,5 + 6)的积木。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); System.out.println(solve(arr)); } } private static int solve (int []arr) { int sum = 0 ; int x = 0 ; int minValue = Integer.MAX_VALUE; for (int i = 0 ; i < arr.length; i++) { x ^= arr[i]; sum += arr[i]; minValue = Math.min(minValue, arr[i]); } if (x != 0 ) { return -1 ; } else { return sum - minValue; } } }
连续字母长度
题目描述
给定一个字符串,只包含大写字母,求在包含同一字母的子串中,长度第 k 长的子串的长度,相同字母只取最长的那个子串。
输入描述
第一行有一个子串 (1 < 长度 <=100),只包含大写字母。
第二行为 k 的值。
输出描述
输出连续出现次数第 k 多的字母的次数。
示例
用例 1
输入
输出
说明
同一字母连续出现的最多的是 A 和 H,四次;
第二多的是 H,3 次,但是 H 已经存在 4 个连续的,故不考虑;
下个最长子串是 BB,所以最终答案应该输出 2。
用例 2
输入
输出
说明
同一字母连续出现的最多的是 A,三次;
第二多的还是 A,两次,但 A 已经存在最大连续次数三次,故不考虑;
下个最长子串是 B,所以输出 1。
用例 3
输入
输出
说明
只含有 3 个包含同一字母的子串,小于 k,输出 - 1。
用例 4
输入
输出
说明
三个子串长度均为 1,所以此时 k = 1,k=2,k=3 这三种情况均输出 1。特此说明,避免歧义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String s = sc.nextLine(); int k = Integer.parseInt(sc.nextLine()); System.out.println(solve(s, k)); } } private static int solve (String s, int k) { if (s.length() < k) { return -1 ; } int []cnt = new int [26 ]; int n = s.length(); for (int i = 0 ; i < n;) { int j = i + 1 ; while (j + 1 < n && s.charAt(j) == s.charAt(i)) { j++; } int index = s.charAt(i) - 'A' ; cnt[index] = Math.max(cnt[index], j - i); i = j; } List<Integer>list = new ArrayList <>(); for (int i = 0 ; i < 26 ; i++) { if (cnt[i] > 0 ) { list.add(cnt[i]); } } if (list.size() < k) { return -1 ; } Arrays.sort(cnt); return cnt[26 - k]; } }
滑动窗口最大和
题目描述
有一个 N 个整数的数组,和一个长度为 M 的窗口,窗口从数组内的第一个数开始滑动直到窗口不能滑动为止,每次窗口滑动产生一个窗口和(窗口内所有数的和),求窗口滑动产生的所有窗口和的最大值。
输入描述
第一行输入一个正整数 N,表示整数个数。(0<N<100000)
第二行输入 N 个整数,整数的取值范围为 [-100,100]。
第三行输入一个正整数 M,M 代表窗口大小,M<=100000,且 M<=N。
输出描述
窗口滑动产生的所有窗口和的最大值。
示例
输入
输出
说明
窗口长度为 3,窗口滑动产生的窗口和分别为 10+20+30=60,20+30+15=65,30+15+23=68,15+23+12=50,所以窗口滑动产生的所有窗口和的最大值为 68。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); int [] arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int m = Integer.parseInt(sc.nextLine()); System.out.println(solve(n, m, arr)); } } private static int solve (int n, int m, int []arr) { int ans = 0 ; int sum = 0 ; for (int i = 0 ; i < m; i++) { sum += arr[i]; } int top = 0 ; ans = Math.max(ans, sum); for (int i = m; i < n; i++) { sum -= arr[top]; sum += arr[i]; top++; ans = Math.max(ans, sum); } return ans; } }
素数之积
题目描述
RSA 加密算法在网络安全世界中无处不在,它利用了极大整数因数分解的困难度,数据越大,安全系数越高,给定一个 32 位正整数,请对其进行因数分解,找出是哪两个素数的乘积。
输入描述
一个正整数 num(0<num<=2147483647)。
输出描述
如果成功找到,以单个空格分割,从小到大输出两个素数;分解失败,请输出 - 1 -1。
示例
示例 1
输入
输出
说明
因数分解后,找到两个素数 3 和 5,使得 3*5=15,按从小到大排列后,输出 3 5。
示例 2
输入
输出
说明
通过因数分解,找不到任何素数,使得他们的乘积为 27,输出 - 1 -1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); System.out.println(solve(n)); } } private static boolean isPrime (int n) { if (n < 2 ) { return false ; } for (int i = 2 ; i <= Math.sqrt(n) + 1 ; i++) { if (n % i == 0 ) { return false ; } } return true ; } private static String solve (int n) { for (int i = 2 ; i <= Math.sqrt(n) + 1 ; i++) { if (isPrime(i) == true && isPrime(n / i) == true && n % i == 0 ) { return new String (i + " " + n / i); } } return new String ("-1 -1" ); } }
仿 LISP 运算
题目描述
小基设计了一种简化版的 LISP 语言,其唯一的语法就是括号要配对。
形如 (OP P1 P2 …),括号内元素由单个空格分割。
其中第一个元素 OP 为操作符,后续元素均为其参数,参数个数取决于操作符类型。
注意
参数 P1, P2 也有可能是另外一个嵌套的 (OP P1 P2 …);
当前 OP 类型为 add /sub/mul /div(全小写),分别代表整数的加减乘除法,简单起见,所有 OP 参数个数均为 2;
题目涉及数字均为整数,可能为负;
不考虑 32 位溢出翻转,计算过程中也不会发生 32 位溢出翻转;
除零错误时,输出 “error”;
除法遇除不尽,向下取整,即 3/2 = 1。
输入格式
输入为长度不超过 512512512 的字符串,用例保证了无语法错误。
输出格式
输出计算结果或者 “error”。
样例
样例 1
输入
输出
解释说明
45 减 45 得 0,12 除以 0 为除零错误,输出 error。
样例 2
输入
输出
解释说明
-7 除以 3 向下取整得 - 3,1 加 - 3 得 - 2。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import java.util.*;import java.util.stream.Collectors;public class Main { static Stack<Integer>numStack = new Stack <>(); static Stack<String>opStack = new Stack <>(); public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String s = sc.nextLine(); int n = s.length(); int pos = 0 ; for (int i = 0 ; i < n; i++) { char ch = s.charAt(i); if (ch == '(' ) { opStack.push(s.substring(i + 1 , i + 4 )); i += 4 ; pos = i + 1 ; } else if (ch == ')' ) { if (pos < i) { numStack.push(Integer.parseInt(s.substring(pos, i))); i += 1 ; pos = i + 1 ; } int num2 = numStack.pop(); int num1 = numStack.pop(); calculate(num1, num2); } else if (ch == ' ' ) { if (pos < i) { numStack.push(Integer.parseInt(s.substring(pos, i))); pos = i + 1 ; } } } while (opStack.size() != 0 ) { int num2 = numStack.pop(); int num1 = numStack.pop(); calculate(num1, num2); } System.out.println(numStack.get(0 )); } } private static void calculate (int num1, int num2) { String op = opStack.pop(); if (op.equals("add" )) { numStack.push(num1 + num2); } else if (op.equals("sub" )) { numStack.push(num1 - num2); } else if (op.equals("mul" )) { numStack.push(num1 * num2); } else if (op.equals("div" )) { if (num2 == 0 ) { System.out.println("error" ); System.exit(0 ); } int x = num1 / num2; if (num1 % num2 != 0 ) { if (x < 0 ) { x -= 1 ; } } numStack.push(x); } } }
贪吃蛇
题目描述
贪吃蛇是一个经典游戏,蛇的身体由若干方格连接而成,身体随蛇头移动。蛇头触碰到食物时,蛇的长度会增加一格。蛇头和身体的任一方格或者游戏版图边界碰撞时,游戏结束。
下面让我们来完成贪吃蛇游戏的模拟:
给定一个 NM 的数组 arr,代表 N M 个方格组成的版图,贪吃蛇每次移动一个方格。
若 arr [i][j] == ‘H’,表示该方格为贪吃蛇的起始位置;
若 arr [i][j] == ‘F’,表示该方格为食物;
若 arr [i][j] == ‘E’,表示该方格为空格。
贪吃蛇初始长度为 1,初始移动方向为向左。
为给定一系列贪吃蛇的移动操作,返回操作后蛇的长度,如果在操作执行完之前已经游戏结束,返回游戏结束时蛇的长度。
输入描述
第一行为空格分隔的字母,代表贪吃蛇的移动操作。字母取值为 U、D、L、R 和 G:
第二行为空格分隔的两个数,指定 N 和 M,为数组的行和列数。
余下 N 行每行是空格分隔的 M 个字母。字母取值为 H、F 和 E:
H 表示贪吃蛇的起始位置(用例保证有且只有一个 H);
F 表示食物;
E 表示该方格为空。
输出描述
输出一个数字,为蛇的长度。
用例 1
输入
1 2 3 4 5 D G G 3 3 F F F F F H E F E
输出
说明
地图表示为:
蛇头 H (Head)
食物 F (Food)
E 表示该方格为空
四个方向分别表示为:
向上 U (up)
向下 D (down)
向左 L (Left)
向右 R (Right)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String []ops = sc.nextLine().split(" " ); int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int n = arr[0 ]; int m = arr[1 ]; String [][]board = new String [n + 1 ][m + 1 ]; for (int i = 0 ; i < n; i++) { board[i] = sc.nextLine().split(" " ); } int []startPos = null ; for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < m; j++) { if ("H" .equals(board[i][j])) { board[i][j] = "E" ; startPos = new int [] {i, j}; break ; } } if (startPos != null ) { break ; } } List<int []>snakeBody = new ArrayList <>(); snakeBody.add(startPos); String direction = "L" ; for (String op : ops) { switch (op) { case "U" : case "D" : case "L" : case "R" : direction = op; break ; case "G" : int []head = snakeBody.get(0 ); int []nextPos = new int [2 ]; switch (direction) { case "U" : nextPos[0 ] = head[0 ] - 1 ; nextPos[1 ] = head[1 ]; break ; case "D" : nextPos[0 ] = head[0 ] + 1 ; nextPos[1 ] = head[1 ]; break ; case "L" : nextPos[0 ] = head[0 ]; nextPos[1 ] = head[1 ] - 1 ; break ; case "R" : nextPos[0 ] = head[0 ]; nextPos[1 ] = head[1 ] + 1 ; break ; } if (nextPos[0 ] < 0 || nextPos[0 ] >= n || nextPos[1 ] < 0 || nextPos[1 ] >= m) { System.out.println(snakeBody.size()); System.exit(0 ); } boolean flag = false ; for (int i = 0 ; i < snakeBody.size() - 1 ; i++) { int [] bodyPart = snakeBody.get(i); if (bodyPart[0 ] == nextPos[0 ] && bodyPart[1 ] == nextPos[1 ]) { flag = true ; break ; } } if (flag) { System.out.println(snakeBody.size()); System.exit(0 ); } if ("E" .equals(board[nextPos[0 ]][nextPos[1 ]])) { List<int []>newBody = new ArrayList <>(); newBody.add(nextPos); newBody.addAll(snakeBody.subList(0 , snakeBody.size() - 1 )); snakeBody = newBody; } else if ("F" .equals(board[nextPos[0 ]][nextPos[1 ]])) { List<int []>newBody = new ArrayList <>(); newBody.add(nextPos); newBody.addAll(snakeBody); snakeBody = newBody; board[nextPos[0 ]][nextPos[1 ]] = "E" ; } break ; } } System.out.println(snakeBody.size()); } } }
解密犯罪时间
题目描述
警察在侦破一个案件时,得到了线人给出的可能犯罪时间,形如 “HH:MM” 表示的时刻。根据警察和线人的约定,为了隐蔽,该时间是修改过的,解密规则为:利用当前出现过的数字,构造下一个距离当前时间最近的时刻,则该时间为可能的犯罪时间。每个出现数字都可以被无限次使用。
输入描述
形如HH:MM的字符串,表示原始输入。
输出描述
形如HH:MM的字符串,表示推理处理的犯罪时间。
备注
可以保证线人给定的字符串一定是合法的。例如,“01:35” 和 “11:08” 是合法的,“1:35” 和 “11:8” 是不合法的。
最近的时刻可能在第二天。
示例
输入
输出
20:12
20:20
23:59
22:22
12:58
15:11
18:52
18:55
23:52
23:53
09:17
09:19
07:08
08:00
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String s = sc.nextLine(); int index = s.indexOf(":" ); boolean []vis = new boolean [10 ]; for (char ch : s.toCharArray()) { if (ch != ':' ) { vis[ch - '0' ] = true ; } } int hour = Integer.parseInt(s.substring(0 , index)), minute = Integer.parseInt(s.substring(index + 1 )), x = Integer.MAX_VALUE; int cur = hour * 60 + minute; int ansHour = 0 , ansMinute = 0 ; for (int i = 0 ; i < 24 ; i++) { if (!(vis[i / 10 ] && vis[i % 10 ])) { continue ; } for (int j = 0 ; j < 60 ; j++) { if (!(vis[j / 10 ] && vis[j % 10 ])) { continue ; } int times = i * 60 + j; int sub = times > cur ? times - cur : 24 * 60 - (cur - times); if (sub < x && sub > 0 ) { x = sub; ansHour = i; ansMinute = j; } } } System.out.printf("%02d:%02d%n" , ansHour, ansMinute); } } }
求满足条件的最长子串的长度
题目描述
给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度,字符串本身是其最长的子串,子串要求:
只包含 1 个字母 (a~z, A~Z),其余必须是数字;
字母可以在子串中的任意位置。
如果找不到满足要求的子串(如全是字母或全是数字),则返回 - 1。
输入描述
输入为只包含字母和数字的字符串。
输出描述
输出满足条件的子串的长度。
示例
示例 1
输入
输出
说明
满足条件的最长子串是 C124 或者 124A,长度都是 4。
示例 2
输入
输出
说明
字符串自身就是满足条件的子串,长度为 2。
示例 3
输入
输出
说明
满足条件的子串为 B9,长度为 2。
示例 4
输入
输出
说明
没有满足要求的子串,返回 - 1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String s = sc.nextLine(); int l = 0 , r = 0 , charCount = 0 , numCount = 0 , ans = -1 ; int n = s.length(); while (r < n) { if (s.charAt(r) >= '0' && s.charAt(r) <= '9' ) { numCount++; } else { charCount++; } if (charCount == 1 && numCount >= 1 ) { ans = Math.max(ans, r - l + 1 ); } while (charCount > 1 ) { if (s.charAt(l) >= '0' && s.charAt(l) <= '9' ) { numCount--; } else { charCount--; } l++; } r++; } System.out.println(ans); } } }
机器人走迷宫
题目描述
机器人走一个X*Y的迷宫,迷宫中有障碍物(用 0 表示),可通行方格用 #表示。机器人从(0,0)的位置走到(X,Y)的位置,且只能向 X、Y 坐标增加的方向走(向下或向前),不能回退。
迷宫中存在两类特殊方格:
不可达方格:机器人在行走路径上不可能走到的方格;
陷阱方格:走进之后无法抵达终点的方格。
要求输出陷阱方格和不可达方格的数量。
输入描述
第一行为房间的 X 和 Y(0<=X/Y <=1000);
第二行为房间中的墙壁障碍物个数 N(0<= N <=X*Y);
接下来会有 N 行墙壁的坐标,同一行中若有多个障碍物,以空格隔开,所有数据输入均合法。
输出描述
输出陷阱方格与不可达方格数量,以空格隔开。
示例
示例 1
输入
1 2 3 4 5 6 7 6 4 5 0 2 1 2 2 2 4 1 5 1
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int n = arr[0 ], m = arr[1 ]; int k = Integer.parseInt(sc.nextLine()); int [][]map = new int [n + 1 ][m + 1 ]; for (int i = 0 ; i < k; i++) { arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); map[arr[0 ]][arr[1 ]] = 1 ; } map[n - 1 ][m - 1 ] = 2 ; dfs(0 , 0 , n, m, map); int ans1 = 0 , ans2 = 0 ; for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < m; j++) { if (map[i][j] == -1 ) { ans1++; } else if (map[i][j] == 0 ) { ans2++; } } } System.out.println(ans1 + " " + ans2); } } private static boolean dfs (int x, int y, int n, int m, int [][]map) { if (map[x][y] == -1 || map[x][y] == 1 || x >= n || y >= m) { return false ; } if (map[x][y] == 2 ) { return true ; } if (map[x][y] == 0 ) { boolean right = dfs(x + 1 , y, n, m, map); boolean up = dfs(x, y + 1 , n, m, map); if (right || up) { map[x][y] = 2 ; } else { map[x][y] = -1 ; } } return map[x][y] == 2 ; } }
高效的任务规划
题目描述
你有 n 台机器编号为 1~n,每台都需要完成一项工作,机器经过配置后都能独立完成一项工作。假设第 i 台机器需要花 B 分钟进行设置,然后开始运行,J 分钟后完成任务。现在需要选择布置工作的顺序,使得用最短的时间完成所有工作。
注意 :不能同时对两台机器进行配置,但配置完成的机器们可以同时执行各自的工作。
输入描述
第一行输入代表总共有 M 组任务数据(1<M<=10)。
每组数据第一行为一个整数指定机器的数量 N(0<N<=1000)。
随后的 N 行每行两个整数,第一个表示 B(0<=B<=10000),第二个表示 J(0<=J<=10000)。
每组数据连续输入,不会用空行分隔。各组任务单独计时。
输出描述
对于每组任务,输出最短完成时间,且每组的结果独占一行。
示例
示例 1
输入
输出
解释
第一行 1 为一组任务,第二行 1 代表只有一台机器,第三行表示该机器配置需 2 分钟,执行需 2 分钟,总耗时 2+2=4 分钟。
示例 2
输入
1 2 3 4 5 6 7 8 2 2 1 1 2 2 3 1 1 2 2 3 3
输出
解释
第一行 2 代表两组任务;
第二行 2 代表第一组任务有 2 个机器;
第三行 1 1 代表机器 1 配置需要 1 分、运行需要 1 分;
第四行 2 2 代表机器 2 配置需要 2 分、运行需要 2 分;
第五行 3 代表第二组任务需要 3 个机器;
第 6-8 行分别表示 3 个机器的配置与运行时间;
第一组最优顺序为机器 2→机器 1:配置总耗时 2+1=3 分钟,机器 2 运行结束时间 3+2=5 分钟,机器 1 运行结束时间 3+1=4 分钟,总耗时 4 分钟;
第二组最优顺序为机器 3→机器 2→机器 1:配置总耗时 3+2+1=6 分钟,机器 3 运行结束时间 6+3=9 分钟,机器 2 运行结束时间 6+2=8 分钟,机器 1 运行结束时间 6+1=7 分钟,总耗时 7 分钟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int m = Integer.parseInt(sc.nextLine()); for (int i = 0 ; i < m; i++) { int n = Integer.parseInt(sc.nextLine()); int []dp = new int [n + 1 ]; int ans = 0 ; int sum = 0 ; int [][]a = new int [n][2 ]; for (int j = 0 ; j < n; j++) { int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); a[j][0 ] = arr[0 ]; a[j][1 ] = arr[1 ]; } Arrays.sort(a, (arr1, arr2)->(arr2[1 ] - arr1[1 ])); for (int j = 0 ; j < n; j++) { dp[j] = sum + a[j][0 ] + a[j][1 ]; sum += a[j][0 ]; ans = Math.max(ans, dp[j]); } System.out.println(ans); } } } }
二叉树遍历
题目描述
根据给定的二叉树结构描述字符串,输出该二叉树按照中序遍历结果字符串。中序遍历顺序为:左子树 → 根结点 → 右子树。
输入描述
输入为由大小写字母、左右大括号、逗号组成的字符串:
字母代表一个节点值;
左右括号内包含该节点的子节点;
左右子节点使用逗号分隔,逗号前为空则表示左子节点为空,没有逗号则表示右子节点为空。
备注 :二叉树节点数最大不超过 100;输入字符串格式是正确的,无需考虑格式错误的情况。
输出描述
输出一个字符串,为二叉树中序遍历各节点值的拼接结果。
示例
示例 1
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 import java.util.*;class TreeNode { char val; TreeNode left; TreeNode right; TreeNode(char x) { val = x; } }public class Main { public static void main (String[] args) { Scanner scanner = new Scanner (System.in); String input = scanner.nextLine().trim(); TreeNode root = parse(input); String result = inorder(root); System.out.println(result); } private static TreeNode parse (String s) { if (s.isEmpty()) return null ; int i = 0 ; char val = s.charAt(i++); TreeNode node = new TreeNode (val); if (i < s.length() && s.charAt(i) == '{' ) { int start = i; int count = 1 ; i++; while (i < s.length() && count > 0 ) { if (s.charAt(i) == '{' ) count++; else if (s.charAt(i) == '}' ) count--; i++; } String children = s.substring(start + 1 , i - 1 ); List<String> parts = splitChildren(children); node.left = parse(parts.get(0 )); node.right = parse(parts.get(1 )); } return node; } private static List<String> splitChildren (String s) { List<String> parts = new ArrayList <>(); int count = 0 ; int splitIndex = -1 ; for (int i = 0 ; i < s.length(); i++) { char c = s.charAt(i); if (c == '{' ) count++; else if (c == '}' ) count--; else if (c == ',' && count == 0 ) { splitIndex = i; break ; } } if (splitIndex != -1 ) { parts.add(s.substring(0 , splitIndex)); parts.add(s.substring(splitIndex + 1 )); } else { parts.add(s); parts.add("" ); } return parts; } private static String inorder (TreeNode root) { if (root == null ) return "" ; return inorder(root.left) + root.val + inorder(root.right); } }
书籍叠放
题目描述
给定一组书的长宽,并且只有当一本书的长宽同时小于另一本书的长宽时,两书才能叠放在一起,求该组书中最多能有多少本书叠放在一起。
输入描述
输入为二维列表形式的书的长宽数据(如[[20,16],[15,11],[10,10],[9,10]])。
输出描述
输出最多可叠放的书籍数量。
示例
示例 1
输入
1 [[20,16],[15,11],[10,10],[9,10]]
输出
解释
前三本可叠放在一起(20,16)→(15,11)→(10,10),第四本宽 10 不小于第三本的宽 10,无法叠放,故最多 3 本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.util.*;import java.util.stream.Collectors;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String s = sc.nextLine().replaceAll("\\[" , "" ).replaceAll("\\]" , "" ); String[] str = s.split("," ); int [][] nums = new int [str.length / 2 ][2 ]; for (int i = 0 ; i < nums.length; i++) { nums[i][0 ] = Integer.parseInt(str[i * 2 ]); nums[i][1 ] = Integer.parseInt(str[i * 2 + 1 ]); } Arrays.sort(nums, (a, b) -> (a[0 ] == b[0 ] ? b[1 ] - a[1 ] : a[0 ] - b[0 ])); int [] dp = new int [nums.length]; Arrays.fill(dp, 1 ); int res = 0 ; for (int [] num : nums) { int left = 0 , right = res; while (left < right) { int mid = (right - left ) / 2 + left; if (dp[mid] < num[1 ]) { left = mid + 1 ; } else { right = mid; } } dp[left] = num[1 ]; if (left == res) { res++; } } System.out.println(res); } } }
区间交集
题目描述
给定一组闭区间,其中部分区间存在交集。任意两个给定区间的交集称为公共区间(如[1,2]和[2,3]的公共区间为[2,2],[3,5]和[3,6]的公共区间为[3,5])。公共区间之间若存在交集,则需要合并(如[1,3]和[3,5]区间存在交集[3,3],需合并为[1,5])。按升序排列输出合并后的区间列表。
输入描述
输入为一组区间列表的简化形式(去掉逗号和括号),区间数 N 满足 0<=N<=1000;
区间元素 X 满足 -10000<=X<=10000。
输出描述
按升序排列输出合并后的区间列表(简化形式,无括号和逗号);
若无公共区间,输出None;
单个区间认定为无公共区间。
示例
示例 1
输入
输出
说明
[0,3]和[1,3]的公共区间为[1,3];
[0,3]和[3,5]的公共区间为[3,3];
[0,3]和[3,6]的公共区间为[3,3];
[1,3]和[3,5]的公共区间为[3,3];
[1,3]和[3,6]的公共区间为[3,3];
[3,5]和[3,6]的公共区间为[3,5];
公共区间列表为[[1,3],[3,3],[3,5]],合并后为[1,5]。
示例 2
输入
输出
说明
[1,6]和[2,5]的交集为[2,5];
[1,6]和[5,7]的交集为[5,6];
[2,5]和[5,7]的交集为[5,5];
公共区间合并后为[2,6]。
示例 3
输入
输出
说明
[1,2]和[3,4]无公共区间,故输出None。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.util.*;import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner in = new Scanner (System.in); String[] str = in.nextLine().split(" " ); int [] arr = new int [str.length]; for (int i = 0 ; i < arr.length; i++) { arr[i] = Integer.parseInt(str[i]); } List<int []> res = new ArrayList <>(); for (int i = 0 ; i < arr.length; i += 2 ) { for (int j = i + 2 ; j < arr.length; j += 2 ) { int left = Math.max(arr[i], arr[j]); int right = Math.min(arr[i + 1 ], arr[j + 1 ]); if (left <= right) { res.add(new int [] {left, right}); } } } int [][] ans = res.toArray(new int [res.size()][]); Arrays.sort(ans, (a, b) -> (a[0 ] == b[0 ] ? a[1 ] - b[1 ] : a[0 ] - b[0 ])); int [][] result = new int [ans.length][2 ]; int index = -1 ; for (int [] an : ans) { if (index == -1 || an[0 ] > result[index][1 ]) { result[++index] = an; } else { result[index][1 ] = Math.max(result[index][1 ], an[1 ]); } } int [][] last = Arrays.copyOf(result, index + 1 ); for (int i = 0 ; i < last.length; i++) { System.out.print(last[i][0 ]); System.out.print(" " ); System.out.print(last[i][1 ]); if (i != last.length - 1 ) { System.out.print(" " ); } } } }
分月饼
题目描述
公司分月饼,有m个员工,买了n个月饼(m <= n),每个员工至少分一个月饼,也可以分到多个。设单人分到最多月饼的个数为Max1,第二多的为Max2,需满足Max1-Max2 <= 3;以此类推,任意相邻排名的月饼数差值都需<=3。问有多少种分月饼的方法?
注意 :不同顺序但数值组合相同的分法算同一种(如 1+3 和 3+1 算一种)。
输入描述
每一行输入m和n,表示m个员工、n个月饼(m <= n)。
输出描述
输出满足条件的分法数量。
示例
示例 1
输入
输出
说明
合法分法:4=1+3、4=2+2(1+3 和 3+1 算同一种)。
示例 2
输入
输出
说明
合法分法:5=1+1+3、5=1+2+3。
示例 3
输入
输出
说明
满足要求的 6 种分法:
12 = 1 + 4 + 7
12 = 2 + 4 + 6
12 = 2 + 5 + 5
12 = 3 + 3 + 6
12 = 3 + 4 + 5
12 = 4 + 4 + 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import java.util.*;import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int m = arr[0 ], n = arr[1 ]; int []a = new int [m]; Arrays.fill(a, 1 ); if (n == m) { System.out.println("1" ); System.exit(0 ); } System.out.println(dfs(m, n - m, a, 0 )); } } private static int dfs (int m, int remaining, int []arr, int index) { if (index == m) { if (remaining == 0 ) { return 1 ; } else { return 0 ; } } if (remaining == 0 ) { if (arr[index - 1 ] - arr[index] <= 3 ) { return 1 ; } else { return 0 ; } } int result = 0 ; for (int i = 0 ; i <= remaining; i++) { int x = arr[index] + i; if (index == 0 || (index > 0 && arr[index - 1 ] >= x && arr[index - 1 ] - x <= 3 )) { arr[index] += i; result += dfs(m, remaining - i, arr, index + 1 ); arr[index] -= i; } } return result; } }
找最小数
题目描述
给一个正整数NUM1(以字符串形式表示),移除N位数字后得到新正整数NUM2,要求NUM2的值最小。
输入描述
第一行为字符串形式的正整数NUM1,长度小于 32;
第二行为需要移除的数字个数(小于NUM1长度)。
输出描述
输出最小值NUM2的数字字符串。
示例
示例 1
输入
输出
说明
移除 2、6、5、7 这四个数字,剩下 1、3、1 按原有顺序排列组成 131,为最小值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.*;import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String s = sc.nextLine(); int n = Integer.parseInt(sc.nextLine()); Stack<Character>stack = new Stack <>(); for (int i = 0 ; i < s.length(); i++) { char ch = s.charAt(i); while (!stack.isEmpty() && stack.peek() > ch && n > 0 ) { stack.pop(); n--; } stack.push(ch); } while (n > 0 ) { stack.pop(); n--; } StringBuilder ans = new StringBuilder (); for (char ch : stack) { if (!(ans.length() == 0 && ch == '0' )) { ans.append(ch); } } System.out.println(ans.length() == 0 ? "0" : ans.toString()); } } }
简易内存池
题目描述
实现一个简易内存池,支持REQUEST(分配内存)和RELEASE(释放内存)两种操作,规则如下:
内存池总大小为 100 字节;
内存分配必须是连续内存,优先从低地址分配;
释放的内存可被再次分配,已释放的空闲内存不能二次释放;
不会释放已申请内存块的中间地址,释放仅针对首地址对应的单个内存块。
输入描述
首行为整数N(0 < N <= 100),表示操作命令的个数;
接下来N行,每行是操作命令,格式为REQUEST=大小或RELEASE=首地址。
输出描述
REQUEST:分配成功返回首地址,内存不足 / 大小为 0 输出error;
RELEASE:释放成功无输出,释放不存在的首地址输出error。
示例
样例 1
输入
输出
样例 2
输入
1 2 3 4 5 6 5 REQUEST=10 REQUEST=20 RELEASE=0 REQUEST=20 REQUEST=10
输出
提示说明
第一条指令:申请 0~9 字节,返回首地址 0;
第二条指令:申请 10~29 字节,返回首地址 10;
第三条指令:释放 0~9 字节,无输出;
第四条指令:0~9 字节不足 20 字节,申请 30~49 字节,返回 30;
第五条指令:申请 0~9 字节,返回 0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 import java.util.*;import java.util.Scanner;public class Main { static final int MAX_VALUE = 100 ; static Map<Integer, Integer>map = new TreeMap <>(); public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); String [][]strings = new String [n][2 ]; for (int i = 0 ; i < n; i++) { strings[i] = sc.nextLine().split("=" ); } for (int i = 0 ; i < n; i++) { int value = Integer.parseInt(strings[i][1 ]); String op = strings[i][0 ]; if (op.equals("REQUEST" )) { request(value); } else if (op.equals("RELEASE" )) { release(value); } else { System.out.println("error" ); } } } } private static void request (int value) { if (value > MAX_VALUE || value <= 0 ) { System.out.println("error" ); return ; } int pre = 0 ; if (map.isEmpty()) { map.put(0 , value); System.out.println("0" ); } else { for (Integer requestHead : map.keySet()) { if (requestHead - pre >= value) { map.put(pre, pre + value); System.out.println(pre); return ; } else { pre = map.get(requestHead); } } if (MAX_VALUE - pre >= value) { map.put(pre, pre + value); System.out.println(pre); } else { System.out.println("error" ); } } } private static void release (int value) { if (map.containsKey(value)) { map.remove(value); } else { System.out.println("error" ); } } }
服务失效判断
题目描述
某系统中有多个唯一标识的服务(字符串,长度 <=10),服务间存在依赖关系(如 A 依赖 B,则 B 故障会导致 A 故障),依赖具有传递性(A 依赖 B、B 依赖 C,C 故障则 A、B 均故障)。给定依赖关系和故障服务列表,输出所有正常服务。
输入描述
第一行:半角逗号分隔的依赖关系列表(格式:服务 1 - 服务 2,表示服务 1 依赖服务 2);
第二行:半角逗号分隔的故障服务列表。
输出描述
输出依赖关系中提及的所有正常服务,按依赖关系列表中出现的次序排序,半角逗号分隔;
无正常服务时输出单个半角逗号。
示例
示例 1
输入
输出
说明
a1 依赖 a2,a2 故障→a1 故障;a2 依赖 a3,a2 故障不影响 a3;
a5 故障不影响 a6;
正常服务为 a6、a3,按依赖列表出现次序输出。
示例 2
输入
输出
说明
a1 依赖 a2,a2 故障→a1 故障,无正常服务,输出单个逗号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.util.*;public class Main { static Map<String, List<String>>map = new HashMap <>(); static Set<String>set = new LinkedHashSet <>(); public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String []strings = sc.nextLine().split("," ); for (String str : strings) { String[]s = str.split("-" ); set.add(s[0 ]); set.add(s[1 ]); map.computeIfAbsent(s[1 ], k->new ArrayList <String>()).add(s[0 ]); } Set<String> badSet = new HashSet <>(); Queue<String>queue = new ArrayDeque <>(); strings = sc.nextLine().split("," ); for (String str : strings) { queue.offer(str); badSet.add(str); } while (!queue.isEmpty()) { String cur = queue.poll(); List<String>list = map.getOrDefault(cur, new ArrayList <>()); for (String str : list) { if (!badSet.contains(str)) { badSet.add(str); queue.offer(str); } } } List<String>ans = new ArrayList <>(); for (String str : set) { if (!badSet.contains(str)) { ans.add(str); } } if (ans.isEmpty()) { System.out.println("," ); } else { System.out.println(String.join("," , ans)); } } } }
图像物体的边界
题目描述
给定M行N列的二维数组(仅包含像素 1 和 5),像素 1 代表的物体的边界定义为:与像素 5 相邻(8 个方向:上、下、左、右、左上、左下、右上、右下)的像素 1 格子;相邻的边界格子属于同一个边界。求像素 1 代表的物体的边界个数。
输入描述
第一行:行数M、列数N(0<M<100,0<N<100);
第二行开始:M行N列的像素数组(仅包含 1 和 5)。
输出描述
输出像素 1 代表的物体的边界个数,无边界输出 0。
示例
示例 1
输入
1 2 3 4 5 6 7 6 6 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5
输出
说明
左上角与 5 相邻的 1 组成 1 个边界;
右下角与 5 相邻的 1 组成 1 个边界;
总边界数为 2。
示例 2
输入
1 2 3 4 5 6 7 6 6 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1
输出
说明
所有与 5 相邻的 1 格子相互相邻,仅构成 1 个边界。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 import java.util.*;public class Main { static int m, n; static int [][]grid; public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String [] strings = sc.nextLine().split(" " ); m = Integer.parseInt(strings[0 ]); n = Integer.parseInt(strings[1 ]); grid = new int [m][n]; for (int i = 0 ; i < m; i++) { grid[i] = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); } for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (grid[i][j] == 5 ) { for (int dx = -1 ; dx < 2 ; dx++) { for (int dy = -1 ; dy < 2 ; dy++) { int x = dx + i; int y = dy + j; if (check(x, y) && grid[x][y] == 1 ) { grid[x][y] = 2 ; } } } } } } int ans = 0 ; for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (grid[i][j] == 2 ) { dfs(i, j); ans++; } } } System.out.println(ans); } } private static boolean check (int x, int y) { if (x < 0 || x >= m || y < 0 || y >= n) { return false ; } return true ; } private static void dfs (int x, int y) { if (!check(x, y) || grid[x][y] != 2 ) { return ; } grid[x][y] = 1 ; for (int dx = -1 ; dx < 2 ; dx++) { for (int dy = -1 ; dy < 2 ; dy++) { int xx = dx + x; int yy = dy + y; dfs(xx, yy); } } } }
跳格子游戏
题目描述
小明和朋友们玩跳格子游戏,每个格子有特定分数score(如[1, -1, -6, 7, -17, 7])。从起点score[0]开始,每次最大步长为k,返回跳到终点score[n-1]时能得到的最大得分。
输入描述
第一行输入格子总数n;
第二行输入每个格子的分数score[i];
第三行输入最大跳步长k。
输出描述
输出能得到的最大得分。
备注
格子总数n和步长k的范围:[1, 100000];
每个格子分数score[i]范围:[-10000, 10000]。
示例
输入
输出
说明
小明从score[0]开始,依次跳到score[1]、score[3]、score[5],总得分1 + (-1) + 7 + 7 = 14,为最大得分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int k = Integer.parseInt(sc.nextLine()); if (arr.length == 1 ) { System.out.println(arr[0 ]); continue ; } int []dp = new int [n]; PriorityQueue<Integer> queue = new PriorityQueue <>((a, b)->(b - a)); for (int i = 0 ; i < n; i++) { if (i == 0 ) { dp[i] = arr[0 ]; } else { dp[i] = queue.peek() + arr[i]; } queue.add(dp[i]); if (i - k >= 0 ) { queue.remove(dp[i - k]); } } System.out.println(dp[n - 1 ]); } } }
数组二叉树
题目描述
二叉树用数组存储:根节点值存于下标 1,下标N的节点,其左子节点存于2N、右子节点存于2N+1;值-1表示节点为空。给定存储二叉树的数组,求从根节点到最小叶子节点的路径(路径由节点值组成)。
输入描述
输入一行为数组内容,元素为正整数(-1表示空节点),元素间用空格分隔;数组第N个元素对应下标N(下标 0 省略);树最多 7 层。
输出描述
输出从根节点到最小叶子节点的路径上的节点值,空格分隔(保证最小叶子节点唯一)。
示例
示例 1
输入
输出
说明
最小叶子节点为 2,路径是 3→7→2。
示例 2
输入
1 5 9 8 -1 -1 7 -1 -1 -1 -1 -1 6
输出
说明
最小叶子节点为 6,路径是 5→8→7→6;数组仅存储至最后一个非空节点,不含 “7” 右子节点的 - 1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int [] array = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int n = array.length; int min = Integer.MAX_VALUE; int min_index = -1 ; for (int i = 0 ; i < n; i++) { if (array[i] != -1 ) { if ((i + 1 ) * 2 - 1 < n && array[(i + 1 ) * 2 - 1 ] != -1 ) continue ; if ((i + 1 ) * 2 < n && array[(i + 1 ) * 2 ] != -1 ) continue ; if (min > array[i]) { min_index = i; min = array[i]; } } } List<Integer> list = new ArrayList <>(); list.add(min); int temp = min_index; while (temp > 0 ) { temp = (temp - 1 ) / 2 ; list.add(array[temp]); } for (int i = list.size() - 1 ; i >= 0 ; i--) { System.out.print(list.get(i) + " " ); } } } }
考古学家
题目描述
考古石碑被打碎成n块,每块有一个 / 若干字符。请输出石碑文字所有可能的组合,并按升序排列。
输入描述
第一行输入n(石碑碎片个数);
第二行依次输入n个碎片的文字内容s。
输出描述
输出所有组合(升序排列),行末无多余空格。
示例
示例 1
输入
输出
示例 2
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.*;public class Main { static boolean []used; static Set<String>ans = new TreeSet <>(); public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int n = Integer.parseInt(sc.nextLine()); String []strings = sc.nextLine().split(" " ); used = new boolean [n + 1 ]; dfs(n, new StringBuilder (), strings); for (String str : ans) { System.out.println(str); } } } private static void dfs (int n, StringBuilder sb, String[]strings) { if (sb.length() == n) { ans.add(sb.toString()); return ; } for (int i = 0 ; i < n; i++) { if (!used[i]) { used[i] = true ; sb.append(strings[i]); dfs(n, sb, strings); sb.deleteCharAt(sb.length() - 1 ); used[i] = false ; } } } }
解压报文
题目描述
为提升传输效率,报文会按规则压缩:n[str]表示方括号内的str重复n次(0 < n <= 100,str仅含小写字母)。给定压缩后的报文,返回解压后的原始报文。
输入描述
输入压缩后的报文:
无额外空格,方括号格式合法;
原始报文无数字,数字仅表示重复次数(无5b/3[8]类输入)。
输出描述
输出解压后的原始报文(长度≤1000)。
示例
示例 1
输入
输出
说明
k重复 3 次,mn重复 2 次,拼接得kkkmnmn。
示例 2
输入
输出
说明
m2[c]解压为mcc,重复 3 次得mccmccmcc。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String s = sc.nextLine(); Stack<Character> strStack = new Stack <>(); StringBuilder numSb = new StringBuilder (); for (char ch : s.toCharArray()) { if (ch == ']' ) { StringBuilder temp = new StringBuilder (); while (!strStack.isEmpty() && strStack.peek() != '[' ) { temp.append(strStack.pop()); } strStack.pop(); while (!strStack.isEmpty() && Character.isDigit(strStack.peek())) { numSb.append(strStack.pop()); } int num = Integer.parseInt(numSb.reverse().toString()); numSb.setLength(0 ); String str = temp.reverse().toString(); for (int i = 0 ; i < num; i++) { for (char ch1 : str.toCharArray()) { strStack.push(ch1); } } } else { strStack.push(ch); } } StringBuilder ans = new StringBuilder (); while (!strStack.isEmpty()) { ans.append(strStack.pop()); } System.out.println(ans.reverse().toString()); } } }
最长的指定瑕疵度的元音子串
题目描述
定义
元音字符串:开头和结尾均为元音字母(aeiouAEIOU)的字符串;
瑕疵度:元音字符串中混杂的非元音字母数量(如abira瑕疵度为 2);
子串:字符串中任意连续字符组成的子序列。
给定字符串,找出指定瑕疵度的最长元音子串,输出其长度;无满足条件的子串则输出 0。
输入描述
首行输入整数flaw(预期瑕疵度,[0, 65535]);
第二行输入仅含a-z/A-Z的字符串(长度(0, 65535])。
输出描述
输出满足条件的元音子串长度。
示例
示例 1
输入
输出
示例 2
输入
输出
示例 3
输入
输出
说明
满足条件的最长元音子串为aabee和eebuu,长度均为 5。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int flaw = Integer.parseInt(sc.nextLine()); String s = sc.nextLine(); Set<Character> set = new HashSet <>(); for (char ch : "aeiouAEIOU" .toCharArray()) { set.add(ch); } int n = s.length(); int cnt = 0 ; List<Integer> pos = new ArrayList <>(); int []num = new int [n + 1 ]; for (int i = 0 ; i < n; i++) { char ch = s.charAt(i); if (set.contains(ch)) { pos.add(i); } else { cnt++; } num[i + 1 ] = cnt; } int l = 0 , ans = 0 ; for (int r = 0 ; r < pos.size(); r++) { int right = pos.get(r); while (l <= r) { int left = pos.get(l); int curFlaw = num[right + 1 ] - num[left + 1 ]; if (curFlaw > flaw) { l++; continue ; } if (curFlaw == flaw) { ans = Math.max(ans, right - left + 1 ); } break ; } } System.out.println(ans); } } }
目录删除
题目描述
某文件系统的目录结构为树状:根目录 ID 为 0,每个目录有唯一 ID,且仅有一个父目录(根目录无父目录)。给定[子目录ID,父目录ID]的父子关系表,以及待删除的目录 ID,删除该目录及其所有子目录后,返回剩余目录 ID 的递增序列。
输入描述
第一行:父子关系表的长度m;
接下来m行:每行一个父子关系对(子目录 ID 父目录 ID);
最后一行:待删除的目录 ID。
输出描述
输出剩余目录 ID 的递增序列,空格分隔。
示例
示例 1
输入
1 2 3 4 5 6 7 5 8 6 10 8 6 0 20 8 2 6 8
输出
说明
删除 8 及其子目录(10、20),剩余目录为 2、6。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int m = Integer.parseInt(sc.nextLine()); Set<Integer>set = new TreeSet <>(); Map<Integer, List<Integer>>map = new HashMap <>(); for (int i = 0 ; i < m; i++) { int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); set.add(arr[1 ]); set.add(arr[0 ]); map.computeIfAbsent(arr[1 ], k->new ArrayList <Integer>()).add(arr[0 ]); } Set<Integer>badNum = new HashSet <>(); Queue<Integer>queue = new ArrayDeque <>(); int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); for (int i = 0 ; i < arr.length; i++) { queue.offer(arr[i]); badNum.add(arr[i]); } while (!queue.isEmpty()) { int x = queue.poll(); List<Integer>list = map.getOrDefault(x, Collections.emptyList()); for (Integer num : list) { if (!badNum.contains(num)) { queue.offer(num); badNum.add(num); } } } Set<Integer>ans = new TreeSet <>(); for (Integer x : set) { if (!badNum.contains(x)) { ans.add(x); } } for (Integer x : ans) { if (x != 0 ) { System.out.print(x + " " ); } } System.out.println(); } } }
火锅
题目描述
火锅中不同时间下菜,每道菜x秒下锅,需煮y秒才刚好合适。你的手速为m(捞菜后至少隔m秒才能再捞,每次捞 1 个),求最多能吃到的刚好合适的菜的数量。
输入描述
第一行:整数n(菜的个数)、m(手速,1 < n, m < 1000);
接下来n行:每行两个数x、y(1 < x, y < 1000),表示x秒下的菜需煮y秒。
输出描述
输出最多能吃到的刚好合适的菜的数量。
示例
示例 1
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int []arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int n = arr[0 ], m = arr[1 ]; int []a = new int [n]; for (int i = 0 ; i < n; i++) { arr = Arrays.stream(sc.nextLine().split(" " )).mapToInt( Integer::parseInt).toArray(); int x = arr[0 ], y = arr[1 ]; a[i] = x + y; } Arrays.sort(a); int cnt = 1 ; int pre = 0 ; for (int i = 1 ; i < a.length; i++) { if (a[i] >= a[pre] + m) { cnt++; pre = i; } } System.out.println(cnt); } } }
服务器广播
题目描述
给定N×N的服务器连接矩阵(matrix[i][j]=1表示服务器i和j直接连接,连接对称且自连),广播可通过直接 / 间接连接传播。求最少需要向几台服务器发送广播,才能让所有服务器接收。
输入描述
输入N行,每行N个 0/1(空格分隔),1<=N<=50。
输出描述
输出最少广播的服务器数量。
示例
示例 1
输入
输出
说明
服务器 0、1、2 互通,只需广播 1 台。
示例 2
输入
输出
说明
3 台服务器互不连接,需分别广播。
示例 3
输入
输出
说明
2 台服务器互通,只需广播 1 台。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); List<String>list = new ArrayList <>(); while (sc.hasNextLine()) { String str = sc.nextLine(); if (str.isEmpty()) { break ; } list.add(str); } sc.close(); int n = list.size(); int [][]matrix = new int [n][n]; for (int i = 0 ; i < n; i++) { matrix[i] = Arrays.stream(list.get(i).split(" " )).mapToInt( Integer::parseInt).toArray(); } Map<Integer, Integer>map = new HashMap <>(); for (int i = 0 ; i < n; i++) { map.put(i, i); } for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { if (matrix[i][j] == 1 && i != j) { int tagI = map.get(i); int tagJ = map.get(j); if (tagI != tagJ) { int max = Math.max(tagI, tagJ); int min = Math.min(tagI, tagJ); for (int k = 0 ; k < n; k++) { if (map.get(k) == max) { map.put(k, min); } } } } } } Set<Integer>ans = new HashSet <>(map.values()); System.out.println(ans.size()); } }
二叉树的广度优先遍历
题目描述
给定二叉树的后序遍历(左→右→父)和中序遍历(左→父→右)结果(节点为大写字母,最多 26 个),输出层次遍历(广度优先)结果。
输入描述
输入一行,为后序遍历和中序遍历结果(空格分隔)。
输出描述
输出层次遍历结果(无空格)。
示例
示例 1
输入
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import java.util.*;public class Main { static class TreeNode { char val; TreeNode left; TreeNode right; TreeNode (char val) { this .val = val; } } public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { String []strings = sc.nextLine().split(" " ); String postOrder = strings[0 ]; String inOrder = strings[1 ]; TreeNode root = build(postOrder, inOrder); bfs(root); } } private static TreeNode build (String postOrder, String inOrder) { if (postOrder.isEmpty() || inOrder.isEmpty()) { return null ; } char rootVal = postOrder.charAt(postOrder.length() - 1 ); TreeNode root = new TreeNode (rootVal); int index = inOrder.indexOf(rootVal); String leftInOrder = inOrder.substring(0 , index); String rightInOrder = inOrder.substring(index + 1 ); int lSize = leftInOrder.length(); String leftPostOrder = postOrder.substring(0 , lSize); String rightPostOrder = postOrder.substring(lSize, postOrder.length() - 1 ); root.left = build(leftPostOrder, leftInOrder); root.right = build(rightPostOrder, rightInOrder); return root; } private static void bfs (TreeNode root) { if (root == null ) { return ; } Queue<TreeNode>queue = new ArrayDeque <>(); queue.offer(root); while (!queue.isEmpty()) { TreeNode curNode = queue.poll(); System.out.print(curNode.val); if (curNode.left != null ) { queue.offer(curNode.left); } if (curNode.right != null ) { queue.offer(curNode.right); } } } }
找单词
题目描述
给定N×N的大写字符数组和一个目标字符串,若字符串按顺序出现在数组中(相邻单元格,单元格不重复使用),输出每个字符的下标序列;否则输出N。
输入描述
第 1 行:数字N(二维数组行数,0<N<=100);
第 2~N+1 行:二维字符数组(每行字符用,分隔);
第 N+2 行:待查找字符串(大写,长度 0<K<1000)。
输出描述
输出下标字符串(格式:行,列,行,列…),无匹配则输出N。
示例
示例 1
输入
1 2 3 4 5 6 4 A,C,C,F C,D,E,D B,E,S,S F,E,C,A ACCESS
输出
1 0,0,0,1,0,2,1,2,2,2,2,3
说明
ACCESS 对应下标依次为 [0,0]、[0,1]、[0,2]、[1,2]、[2,2]、[2,3]。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 import java.util.*;public class Main { static int n; static char [][]grid; static boolean [][]used; static int []dx = {-1 , 0 , 0 , 1 }; static int []dy = {0 , -1 , 1 , 0 }; static String word; public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { n = Integer.parseInt(sc.nextLine()); grid = new char [n][n]; used = new boolean [n][n]; for (int i = 0 ; i < n; i++) { String []strings = sc.nextLine().split("," ); for (int j = 0 ; j < n; j++) { grid[i][j] = strings[j].charAt(0 ); } } word = sc.nextLine(); for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { if (grid[i][j] == word.charAt(0 )) { List<int []>path = new ArrayList <>(); path.add(new int [] {i, j}); if (dfs(0 , i, j, path )) { return ; } } } } System.out.println("N" ); } } private static boolean dfs (int cnt, int x, int y, List<int []>path) { if (x < 0 || x >= n || y < 0 || y >= n || used[x][y] || grid[x][y] != word.charAt(cnt)) { return false ; } if (cnt == word.length() - 1 ) { for (int i = 0 ; i < path.size(); i++) { System.out.print(path.get(i)[0 ] + "," + path.get(i)[1 ]); if (i < path.size() - 1 ) { System.out.print("," ); } } return true ; } used[x][y] = true ; for (int i = 0 ; i < 4 ; i++) { int xx = x + dx[i], yy = y + dy[i]; path.add(new int [] {xx, yy}); if (dfs(cnt + 1 , xx, yy, path)) { return true ; } path.remove(path.size() - 1 ); } used[x][y] = false ; return false ; } }
招聘
题目描述
给定n场面试的起止时间(Si < Ei),每名面试官每次只能面试 1 人,完成后可立即开始下一场,且每人最多面试m人次。求至少需要的面试官数量。
输入描述
第一行:面试官最多面试人次m(1<=m<=500);
第二行:面试场次n(1<=n<=500);
接下来n行:每场面试的起始、结束时间(空格分隔)。
输出描述
输出至少需要的面试官数量。
示例
示例 1
输入
输出
说明
5 场无重叠面试,每人最多 2 场,需 3 人。
示例 2
输入
输出
说明
3 场无重叠,每人最多 3 场,需 1 人。
示例 3
输入
输出
说明
[5,10] 和 [8,35] 重叠,需 2 人。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.util.*;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { int m = Integer.parseInt(sc.nextLine()); int n = Integer.parseInt(sc.nextLine()); int [][]arr = new int [n][2 ]; for (int i = 0 ; i < n; i++) { String []strings = sc.nextLine().split(" " ); arr[i][0 ] = Integer.parseInt(strings[0 ]); arr[i][1 ] = Integer.parseInt(strings[1 ]); } Arrays.sort(arr, (a, b)->a[1 ] - b[1 ]); List<List<Integer>> lists = new ArrayList <>(); for (int i = 0 ; i < n; i++) { lists.add(new ArrayList <>()); } for (int []range : arr) { int start = range[0 ]; int end = range[1 ]; for (List<Integer>list : lists) { if (list.size() < m && (list.isEmpty() || list.get(list.size() - 1 ) <= start)) { list.add(end); break ; } } } int cnt = 0 ; for (List<Integer> list : lists) { if (!list.isEmpty()) { cnt++; } } System.out.println(cnt); } } }
斗地主之顺子
题目描述
斗地主中顺子规则:由至少 5 张连续递增的牌组成(顺序:3,4,5,6,7,8,9,10,J,Q,K,A,2),且不含 2。给定 13 张牌,输出所有合法顺子(按首张牌升序,无则输出 No)。
输入描述
输入 13 张牌(空格分隔,无大小王)。
输出描述
每行输出一个顺子(空格分隔);无则输出 No。
示例
示例 1
输入
1 2 9 J 2 3 4 K A 7 9 A 5 6
输出
示例 2
输入
1 2 9 J 10 3 4 K A 7 Q A 5 6
输出
示例 3
输入
1 2 9 9 9 3 4 K A 10 Q A 5 6
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import java.util.*;public class Main { static String[] order = {"3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "J" , "Q" , "K" , "A" }; static Map<String, Integer>map = new HashMap <>(); public static void main (String[] args) { Scanner sc = new Scanner (System.in); while (sc.hasNextLine()) { for (int i = 0 ; i < order.length; i++) { map.put(order[i], i); } String []strings = sc.nextLine().split(" " ); Set<String>uniqueCard = new HashSet <>(); for (String card : strings) { if (!card.equals("2" )) { uniqueCard.add(card); } } List<String>list = new ArrayList <>(uniqueCard); list.sort(Comparator.comparingInt(map::get)); List<List<String>>result = new ArrayList <>(); int n = list.size(); int i = 0 ; while (i < n) { int start = i; while (i + 1 < n && map.get(list.get(i + 1 )) == map.get(list.get(i)) + 1 ) { i++; } List<String>curList = list.subList(start, i + 1 ); if (curList.size() >= 5 ) { result.add(new ArrayList <>(curList)); } i++; } if (result.isEmpty()) { System.out.println("No" ); } else { for (List<String>strList : result) { System.out.println(String.join(" " , strList)); } } } } }