题目链接

刷题链接:https://www.nowcoder.com/exam/oj/ta?tpId=37
参考博客:http://www.amoscloud.com/?cat=56

HJ1 字符串最后一个单词的长度

方法1:用Java的Scanner 类的特性

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. String word = "";
  6. while (scan.hasNext()) {
  7. word = scan.next();
  8. }
  9. System.out.println(word.length());
  10. }
  11. }

HJ2 计算某字符出现次数

描述
写出一个程序,接受一个由字母、数字和空格组成的字符串,和一个字符,然后输出输入字符串中该字符的出现次数。(不区分大小写字母)
数据范围: [1,1000]

输入描述:
第一行输入一个由字母和数字以及空格组成的字符串,第二行输入一个字符。

输出描述:
输出字符串中含有该字符的个数。(不区分大小写字母)

代码:

  1. import java.util.*;
  2. public class Main{
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while(scan.hasNext()) {
  6. char[] arr = scan.nextLine().toLowerCase().toCharArray();
  7. String str = scan.nextLine().toLowerCase();
  8. int count = 0;
  9. for(int i = 0; i < arr.length; i++){
  10. if(arr[i] == str.charAt(0)){
  11. count++;
  12. }
  13. }
  14. System.out.println(count);
  15. }
  16. }
  17. }

HJ3 明明的随机数

描述
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数( N≤1000 ),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作(同一个测试用例里可能会有多组数据(用于不同的调查),希望大家能正确处理)。

注:测试用例保证输入参数的正确性,答题者无需验证。测试用例不止一组。
当没有新的输入时,说明输入结束。
数据范围:n在[1, 1000] ,输入的数字大小满足 [1, 500]

输入描述:
注意:输入可能有多组数据(用于不同的调查)。每组数据都包括多行,第一行先输入随机整数的个数 N ,接下来的 N 行再输入相应个数的整数。具体格式请看下面的”示例”。

输出描述:
返回多行,处理后的结果

方法1:桶排序。

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. boolean[] map = new boolean[501];
  8. for (int i = 0; i < n; i++) {
  9. int num = scan.nextInt();
  10. map[num] = true;
  11. }
  12. for (int i = 1; i < 501; i++) {
  13. if (map[i]) {
  14. System.out.println(i);
  15. }
  16. }
  17. }
  18. }
  19. }

HJ4 固定长度分割字符串

描述
•连续输入字符串,请按长度为8拆分每个输入字符串并进行输出;
•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。
(注:本题有多组输入)

输入描述:
连续输入字符串(输入多次,每个字符串长度小于等于100)

输出描述:
依次输出所有分割后的长度为8的新字符串

方法1:补全法。

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. // 1. 长度不是8的整数倍,统一补足8个0
  8. if (str.length() % 8 != 0) {
  9. str = str + "00000000";
  10. }
  11. // 2. 固定长度截取,并打印
  12. while (str.length() >= 8) {
  13. System.out.println(str.substring(0, 8));
  14. str = str.substring(8);
  15. }
  16. }
  17. }
  18. }

HJ5 进制转换

描述:写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。

数据范围:保证结果在int范围内
注意本题有多组输入

输入描述:
输入一个十六进制的数值字符串。注意:一个用例会同时有多组输入数据,请参考帖子https://www.nowcoder.com/discuss/276 处理多组输入的问题。

输出描述:
输出该数值的十进制字符串。不同组的测试用例用\n隔开。

方法1:手动转换

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String hex = scan.nextLine().substring(2);
  7. int num = 0;
  8. int len = hex.length();
  9. for (int i = len - 1; i >= 0; i--) {
  10. int temp = hexToNum(hex.charAt(i));
  11. num += temp * Math.pow(16, len - 1 - i);
  12. }
  13. System.out.println(num);
  14. }
  15. }
  16. private static int hexToNum(char c) {
  17. switch (c) {
  18. case 'A':
  19. return 10;
  20. case 'B':
  21. return 11;
  22. case 'C':
  23. return 12;
  24. case 'D':
  25. return 13;
  26. case 'E':
  27. return 14;
  28. case 'F':
  29. return 15;
  30. default:
  31. return Integer.parseInt(String.valueOf(c));
  32. }
  33. }
  34. }

方法2:使用API

  1. import java.util.*;
  2. public class Main {
  3. // 方法2:使用Java的API
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. String str = scan.nextLine();
  8. int num = Integer.parseInt(str.substring(2), 16);
  9. System.out.println(num);
  10. }
  11. }
  12. }

HJ6 质数因子

描述:
输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )

输入描述:
输入一个整数

输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。最后一个数后面也要有空格。

方法1:循环相除法。

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int num = scan.nextInt();
  7. StringBuilder sb = new StringBuilder();
  8. for (int i = 2; i <= Math.sqrt(num); i++) {
  9. while (num % i == 0) {
  10. sb.append(i);
  11. sb.append(" ");
  12. num = num / i;
  13. }
  14. }
  15. // num 最后有两种可能:1或某个质数
  16. if (num != 1) {
  17. sb.append(num);
  18. sb.append(" ");
  19. }
  20. System.out.println(sb);
  21. }
  22. }
  23. }

HJ8 合并表记录

描述
数据表记录包含表索引index和数值value(int范围的正整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照index值升序进行输出。

方法1:Jdk8的流式编程

  1. import java.util.*;
  2. import java.util.stream.Collectors;
  3. public class Main {
  4. public static void main(String[] args) {
  5. Scanner sc = new Scanner(System.in);
  6. while (sc.hasNext()) {
  7. int num = sc.nextInt();
  8. Map<Integer, Integer> map = new HashMap<>();
  9. for (int i = 0; i < num; i++) {
  10. int key=sc.nextInt();
  11. int value=sc.nextInt();
  12. // 有key 就相加,没有key 就put
  13. map.put(key, map.getOrDefault(key, 0) + value);
  14. }
  15. // 这一句用到好多jdk8的新语法啊
  16. List<Map.Entry<Integer, Integer>> collect = map.entrySet().stream().sorted(
  17. ((o1, o2) -> {
  18. return o1.getKey() - o2.getKey();
  19. })
  20. ).collect(Collectors.toList());
  21. for (Map.Entry<Integer, Integer> entry :
  22. collect) {
  23. System.out.println(entry.getKey() + " " + entry.getValue() );
  24. }
  25. }
  26. }
  27. }

方法2:哈希表和有序表

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. HashMap<Integer, Integer> map = new HashMap<>();
  6. int num = scan.nextInt();
  7. while (scan.hasNext()) {
  8. for (int i = 0; i < num; i++) {
  9. int key = scan.nextInt();
  10. int value = scan.nextInt();
  11. if (!map.containsKey(key)) {
  12. map.put(key, value);
  13. } else {
  14. map.put(key, map.get(key) + value);
  15. }
  16. }
  17. // 把map的keySet 排序
  18. TreeSet<Integer> treeSet = new TreeSet<>(map.keySet());
  19. for (Integer key : treeSet) {
  20. System.out.println(key + " " + map.get(key));
  21. }
  22. }
  23. }
  24. }

HJ9 整数逆序不含重复数字

描述
输入一个 int 型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数。
保证输入的整数最后一位不是 0 。

输入描述:
输入一个int型整数

输出描述:
按照从右向左的阅读顺序,返回一个不含重复数字的新的整数

示例1
输入:9876673
输出:37689

方法1:求余加哈希表。

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while(scan.hasNext()){
  6. int num = scan.nextInt();
  7. boolean[] arr = new boolean[10];
  8. StringBuilder sb = new StringBuilder();
  9. // 数组相当于一个哈希表,用来判断某个数字是否出现过
  10. while(num != 0){
  11. int remainder = num % 10;
  12. if(arr[remainder] == false){
  13. sb.append(remainder);
  14. arr[remainder] = true;
  15. }
  16. num = num / 10;
  17. }
  18. System.out.println(sb);
  19. }
  20. }
  21. }

HJ10 统计字符种类

描述:编写一个函数,计算字符串中含有的不同字符的个数。字符在 ASCII 码范围内( 0~127 ,包括 0 和 127 ),换行表示结束符,不算在字符里。不在范围内的不作统计。多个相同的字符只计算一次。
例如,对于字符串 abaca 而言,有 a、b、c 三种不同的字符,因此输出 3 。

输入描述:输入一行没有空格的字符串。

输出描述:输出字符串中范围在(0~127,包括0和127)字符的种数。

示例1
输入:abcb
输出:3

方法1:桶排序

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. int count = getCount(str);
  8. System.out.println(count);
  9. }
  10. }
  11. // 桶排序
  12. public static int getCount(String str) {
  13. int count = 0;
  14. boolean[] flag = new boolean[128];
  15. for (int i = 0; i < str.length(); i++) {
  16. char c = str.charAt(i);
  17. if (!flag[c]) {
  18. flag[c] = true;
  19. count++;
  20. }
  21. }
  22. return count;
  23. }
  24. }

HJ11 数字颠倒

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. String str = scan.nextLine();
  6. StringBuilder sb = new StringBuilder(str);
  7. sb.reverse();
  8. System.out.println(sb);
  9. }
  10. }

HJ12 字符串反转

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. // 将字符串变成char数组再倒序输出
  8. char[] chars = str.toCharArray();
  9. for (int i = chars.length - 1; i >= 0; i--) {
  10. System.out.print(chars[i]);
  11. }
  12. System.out.println();
  13. }
  14. }
  15. }

HJ13 句子逆序

描述:将一个英文语句以单词为单位逆序排放。例如“I am a boy”,逆序排放后为“boy a am I”
所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符
数据范围:输入的字符串长度满足 【1,1000】
注意本题有多组输入

输入描述:输入一个英文语句,每个单词用空格隔开。保证输入只包含空格和字母。

输出描述:得到逆序的句子

示例1
输入:I am a boy
输出:boy a am I

方法1:字符串用空格分隔

  1. import java.util.*;
  2. public class Main{
  3. // 方法2:分割逆序拼接
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. String str = scan.nextLine();
  8. String[] arr = str.split(" ");
  9. StringBuilder sb = new StringBuilder();
  10. for (int i = arr.length - 1; i >= 0; i--) {
  11. sb.append(arr[i]).append(" ");
  12. }
  13. System.out.println(sb);
  14. }
  15. }
  16. }

方法2:两次逆序。

  1. import java.util.*;
  2. public class Main {
  3. // 方法1:两次反转
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. String str = scan.nextLine();
  8. char[] arr = str.toCharArray();
  9. int len = arr.length;
  10. int start = 0;
  11. for (int i = 0; i <= len; i++) {
  12. // 第一次反转,对单词进行反转
  13. if (i == len || arr[i] == ' ') {
  14. reverse(arr, start, i - 1);
  15. start = i + 1;
  16. }
  17. }
  18. // 第二次反转,对整个字符串进行反转
  19. reverse(arr, 0, len - 1);
  20. System.out.println(new String(arr));
  21. }
  22. }
  23. // 对数组[start, end]这段区间进行反转
  24. public static void reverse(char[] arr, int start, int end) {
  25. while (start < end) {
  26. char temp = arr[start];
  27. arr[start] = arr[end];
  28. arr[end] = temp;
  29. start++;
  30. end--;
  31. }
  32. }
  33. }

HJ14 字符串排序

描述
给定 n 个字符串,请对 n 个字符串按照字典序排列。

数据范围: ,字符串长度满足
输入描述:
输入第一行为一个正整数n(1≤n≤1000),下面n行为n个字符串(字符串长度≤100),字符串中只含有大小写字母。
输出描述:
数据输出n行,输出结果为按照字典序排列的字符串。

方法1:手写快速排序,定义比较规则

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. String count = scan.nextLine();
  6. int len = Integer.parseInt(count);
  7. String[] arr = new String[len];
  8. for (int i = 0; i < len; i++) {
  9. arr[i] = scan.nextLine();
  10. }
  11. quickSort(arr, 0, arr.length - 1);
  12. for (String str : arr) {
  13. System.out.println(str);
  14. }
  15. }
  16. private static void quickSort(String[] arr, int low, int high) {
  17. if (low < high) {
  18. int pos = partition(arr, low, high);
  19. quickSort(arr, low, pos - 1);
  20. quickSort(arr, pos + 1, high);
  21. }
  22. }
  23. private static int partition(String[] arr, int low, int high) {
  24. String pivot = arr[low];
  25. int lt = low;
  26. int gt = high;
  27. for (int i = low + 1; i <= gt; i++) {
  28. int compare = compareTo(arr[i], pivot);
  29. if (compare < 0) {
  30. swap(arr, i, lt);
  31. lt++;
  32. } else {
  33. swap(arr, i, gt);
  34. gt--;
  35. i--;
  36. }
  37. }
  38. return lt;
  39. }
  40. // 定义两个字符串的排序规则
  41. private static int compareTo(String a, String b) {
  42. int i = 0;
  43. char[] arr1 = a.toCharArray();
  44. char[] arr2 = b.toCharArray();
  45. // 逐个比较
  46. while (i < arr1.length && i < arr2.length) {
  47. if (arr1[i] == arr2[i]) {
  48. i++;
  49. } else if (arr1[i] < arr2[i]) {
  50. return -1;
  51. } else {
  52. return 1;
  53. }
  54. }
  55. // 长度一样,说明两个字符串一样
  56. if (arr1.length == arr2.length) {
  57. return 0;
  58. }
  59. // a短,返回-1;b短,返回1
  60. if (i == arr1.length) {
  61. return -1;
  62. } else {
  63. return 1;
  64. }
  65. }
  66. private static void swap(String[] arr, int i, int j) {
  67. String temp = arr[i];
  68. arr[i] = arr[j];
  69. arr[j] = temp;
  70. }
  71. }

方法2:使用API

  1. import java.util.*;
  2. public class Main {
  3. // 方法2:使用API
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. String count = scan.nextLine();
  7. int len = Integer.parseInt(count);
  8. String[] arr = new String[len];
  9. for (int i = 0; i < len; i++) {
  10. arr[i] = scan.nextLine();
  11. }
  12. Arrays.sort(arr);
  13. for (String str : arr) {
  14. System.out.println(str);
  15. }
  16. }
  17. }

HJ15 求二进制中1的个数

描述:输入一个 int 型的正整数,计算出该 int 型数据在内存中存储时 1 的个数。

输入描述:输入一个整数(int类型)

输出描述:这个数转换成2进制后,输出1的个数

示例1
输入:5
输出:2

方法1:减一消除法。
用&运算会很巧妙,num & (num - 1),会把num二进制表示中最右侧的1 给消除掉, 每次消除一次就记录次数,直到num变成0,就会得到有多少个1.

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int num = scan.nextInt();
  7. int count = 0;
  8. while (num != 0) {
  9. count++;
  10. num = num & (num - 1);
  11. }
  12. System.out.println(count);
  13. }
  14. }
  15. }

HJ16 购物单

HJ17 坐标移动

方法1:正则加哈希

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. Map<Character, Integer> map = new HashMap<>();
  6. while (scan.hasNext()) {
  7. String str = scan.nextLine();
  8. String[] arr = str.split(";");
  9. String regex = "[ADWS]\\d{1}\\d?";
  10. int x = 0;
  11. int y = 0;
  12. for (int i = 0; i < arr.length; i++) {
  13. if (arr[i].matches(regex)) {
  14. map.put(arr[i].charAt(0), map.getOrDefault(arr[i].charAt(0), 0) + Integer.parseInt(arr[i].substring(1)));
  15. }
  16. }
  17. x = x - map.get('A') + map.get('D');
  18. y = y - map.get('S') + map.get('W');
  19. System.out.println(x + "," + y);
  20. map.clear();
  21. }
  22. scan.close();
  23. }
  24. }

方法2:正则表达式

  1. import java.util.*;
  2. public class Main {
  3. // 方法2:正则表达式
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. String str = scan.nextLine();
  8. String[] arr = str.split(";");
  9. String regex = "[WASD][0-9]{1,2}";
  10. int x = 0;
  11. int y = 0;
  12. for (int i = 0; i < arr.length; i++) {
  13. // 1. 正则表达式匹配合法的字符串
  14. if (!arr[i].matches(regex)) {
  15. continue;
  16. }
  17. // 2. 截取字符串中后面的数值部分,
  18. int digit = Integer.parseInt(arr[i].substring(1));
  19. // 3. 根据移动方向,改变坐标值
  20. switch (arr[i].charAt(0)) {
  21. case 'W':
  22. y += digit;
  23. break;
  24. case 'S':
  25. y -= digit;
  26. break;
  27. case 'A':
  28. x -= digit;
  29. break;
  30. case 'D':
  31. x += digit;
  32. break;
  33. }
  34. }
  35. System.out.println(x + "," + y);
  36. }
  37. }
  38. }

HJ19 简单错误记录

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. Map<String, Integer> map = new LinkedHashMap<>();
  6. String tstr = null;
  7. while (scan.hasNext()) {
  8. tstr = scan.nextLine();
  9. String[] str = tstr.split("\\s+");
  10. String fname = str[0].substring(str[0].lastIndexOf("\\") + 1);
  11. fname = fname.substring(Math.max(fname.length() - 16, 0)) + " " + str[1]; //max 最快推荐 ?:也可以 if太麻烦
  12. Integer tmp = map.get(fname); //get==null较快写法
  13. if (tmp == null) {
  14. map.put(fname, 1);
  15. } else {
  16. map.put(fname, tmp + 1);
  17. }
  18. }
  19. int count = 0;
  20. for (Map.Entry<String, Integer> it : map.entrySet()) {
  21. if (map.size() - count <= 8) {
  22. System.out.println(it.getKey() + " " + it.getValue());
  23. }
  24. count++;
  25. }
  26. }
  27. }

HJ20 密码验证合格程序

方法1:手动检查

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. StringBuilder sb = new StringBuilder();
  6. String str = null;
  7. while (scan.hasNext()) {
  8. str = scan.nextLine();
  9. char[] arr = str.toCharArray();
  10. boolean[] flag = new boolean[4];
  11. // 1. 长度没有超过8位
  12. if (arr.length < 9) {
  13. sb.append("NG").append("\n");
  14. continue;
  15. }
  16. // 2. 至少有3种不同类型的符号
  17. for (int i = 0; i < arr.length; i++) {
  18. if ('A' <= arr[i] && arr[i] <= 'Z') {
  19. flag[0] = true;
  20. } else if ('a' <= arr[i] && arr[i] <= 'z') {
  21. flag[1] = true;
  22. } else if ('0' <= arr[i] && arr[i] <= '9') {
  23. flag[2] = true;
  24. } else {
  25. flag[3] = true;
  26. }
  27. }
  28. int count = 0;
  29. for (int i = 0; i < 4; i++) {
  30. if (flag[i]) {
  31. count++;
  32. }
  33. }
  34. // 3. 不能有长度大于2的包含公共元素的子串重复
  35. boolean sign = true;
  36. for (int i = 0; i < arr.length - 5; i++) {
  37. for (int j = i + 3; j < arr.length - 2; j++) {
  38. if (arr[i] == arr[j] && arr[i + 1] == arr[j + 1] && arr[i + 2] == arr[j + 2]) {
  39. sign = false;
  40. }
  41. }
  42. }
  43. if (count >= 3 && sign) {
  44. sb.append("OK").append("\n");
  45. } else {
  46. sb.append("NG").append("\n");
  47. }
  48. }
  49. System.out.println(sb);
  50. }
  51. }

方法2:正则表达式匹配

  1. import java.util.*;
  2. import java.util.regex.*;
  3. public class Main {
  4. public static void main(String[] arg) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. String str = scan.next();
  8. if (str.length() <= 8) {
  9. System.out.println("NG");
  10. continue;
  11. }
  12. if (!getMatch(str)) {
  13. System.out.println("NG");
  14. continue;
  15. }
  16. if (hasDuplicatedString(str, 0, 3)) {
  17. System.out.println("NG");
  18. continue;
  19. }
  20. System.out.println("OK");
  21. }
  22. }
  23. // 2. 包括大小写字母.数字.其它符号,至少三种
  24. private static boolean getMatch(String str) {
  25. int count = 0;
  26. String[] regex = {"[a-z]", "[A-Z]", "[0-9]", "[^a-zA-Z0-9]"};
  27. for (int i = 0; i < regex.length; i++) {
  28. Pattern pattern = Pattern.compile(regex[i]);
  29. Matcher matcher = pattern.matcher(str);
  30. if (matcher.find()) {
  31. count++;
  32. }
  33. }
  34. return count >= 3;
  35. }
  36. // 3. 校验是否有重复子串
  37. private static boolean hasDuplicatedString(String str, int left, int right) {
  38. if (right >= str.length()) {
  39. return false;
  40. }
  41. if (str.substring(right).contains(str.substring(left, right))) {
  42. return true;
  43. } else {
  44. return hasDuplicatedString(str, left + 1, right + 1);
  45. }
  46. }
  47. }

HJ21 简单密码

方法1:直接按照规则进行变换

  1. import java.util.*;
  2. public class Main {
  3. // 方法1:直接按照规则变换
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. String str;
  7. while (scan.hasNext()) {
  8. str = scan.next();
  9. StringBuilder sb = new StringBuilder();
  10. for (int i = 0; i < str.length(); i++) {
  11. char c = str.charAt(i);
  12. if (c >= 'A' && c < 'Z') {
  13. c = (char) (c - 'A' + 'b');
  14. } else if (c == 'Z') {
  15. c = 'a';
  16. } else if (c >= 'a' && c <= 'c') {
  17. c = '2';
  18. } else if (c >= 'd' && c <= 'f') {
  19. c = '3';
  20. } else if (c >= 'g' && c <= 'i') {
  21. c = '4';
  22. } else if (c >= 'j' && c <= 'l') {
  23. c = '5';
  24. } else if (c >= 'm' && c <= 'o') {
  25. c = '6';
  26. } else if (c >= 'p' && c <= 's') {
  27. c = '7';
  28. } else if (c >= 't' && c <= 'v') {
  29. c = '8';
  30. } else if (c >= 'w' && c <= 'z') {
  31. c = '9';
  32. }
  33. sb.append(c);
  34. }
  35. System.out.println(sb);
  36. }
  37. }
  38. }

方法2:哈希表

  1. import java.util.*;
  2. public class Main {
  3. // 定义map容器,存储按键对应数字字符
  4. private static Map<String, String> map = new HashMap<>();
  5. // 静态初始化map
  6. static {
  7. map.put("1", "1");
  8. map.put("abc", "2");
  9. map.put("def", "3");
  10. map.put("ghi", "4");
  11. map.put("jkl", "5");
  12. map.put("mno", "6");
  13. map.put("pqrs", "7");
  14. map.put("tuv", "8");
  15. map.put("wxyz", "9");
  16. map.put("0", "0");
  17. }
  18. public static void main(String[] args) {
  19. Scanner scan = new Scanner(System.in);
  20. while (scan.hasNext()) {
  21. String str = scan.nextLine();
  22. char[] arr = str.toCharArray();
  23. StringBuilder sb = new StringBuilder();
  24. for (char c : arr) {
  25. if (c >= '0' && c <= '9') {
  26. sb.append(c);
  27. } else if (c >= 'A' && c <= 'Y') { // 如果是A~Y的大写字母则需要将其+32位转换成小写再向后移1位
  28. char newChar = (char) (c + 32 + 1);
  29. sb.append(newChar);
  30. } else if (c == 'Z') { // 如果是Z,则加密成a
  31. sb.append("a");
  32. } else {
  33. Set<String> keys = map.keySet();
  34. for (String key : keys) {
  35. if (key.contains(String.valueOf(c)))
  36. sb.append(map.get(key));
  37. }
  38. }
  39. }
  40. System.out.print(sb.toString());
  41. }
  42. }
  43. }


HJ22 汽水瓶问题

描述
某商店规定:三个空汽水瓶可以换一瓶汽水,允许向老板借空汽水瓶(但是必须要归还)。
小张手上有n个空汽水瓶,她想知道自己最多可以喝到多少瓶汽水。
数据范围:输入的正整数满足 1 \le n \le 100 \1≤n≤100

注意:本题存在多组输入。输入的 0 表示输入结束,并不用输出结果。
输入描述:
输入文件最多包含 10 组测试数据,每个数据占一行,仅包含一个正整数 n( 1<=n<=100 ),表示小张手上的空汽水瓶数。n=0 表示输入结束,你的程序不应当处理这一行。

输出描述:
对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0。

递归问题
根据题意可得:
拿出2个瓶子、再向老板借1个空瓶,换来一瓶水,喝完后把空瓶还给老板,也就是说用2个空瓶可以喝到1瓶水,所以可以总结递推公式:f(n) = f(n - 2) + 1;也可以直接推理出 n / 2 就是结果。

方法1:递归

  1. import java.util.*;
  2. public class Main {
  3. // 方法1:递归
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. int n = scan.nextInt();
  8. if (n == 0) {
  9. return;
  10. }
  11. int m = drink(n);
  12. System.out.println(m);
  13. }
  14. }
  15. public static int drink(int n) {
  16. if (n == 1) {
  17. return 0;
  18. }
  19. if (n == 2) {
  20. return 1;
  21. }
  22. return drink(n - 2) + 1;
  23. }
  24. }

方法2:直接计算。

  1. import java.util.*;
  2. public class Main {
  3. // 方法2:直接计算结果
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. int n = scan.nextInt();
  8. if (n == 0) {
  9. return;
  10. }
  11. System.out.println(n / 2);
  12. }
  13. }
  14. }


HJ23 删除字符串中出现次数最少的字符

方法1:哈希表。

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while(scan.hasNext()){
  6. String str = scan.nextLine();
  7. // 1. 数组做哈希表,统计每个字符出现的次数
  8. int[] arr = new int[26];
  9. for (int i = 0; i < str.length(); i++) {
  10. int index = str.charAt(i) - 'a';
  11. arr[index]++;
  12. }
  13. // 2. 找到出现次数最小的次数
  14. int min = Integer.MAX_VALUE;
  15. for (int i = 0; i < 26; i++) {
  16. if (arr[i] != 0 && arr[i] < min) {
  17. min = arr[i];
  18. }
  19. }
  20. // 3. 再次遍历字符串,过滤出现次数最少的字符
  21. StringBuilder sb = new StringBuilder();
  22. for (int i = 0; i < str.length(); i++) {
  23. int index = str.charAt(i) - 'a';
  24. if (arr[index] != min) {
  25. sb.append(str.charAt(i));
  26. }
  27. }
  28. System.out.println(sb);
  29. }
  30. }
  31. }


HJ26 字符串排序

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. // 1. 筛选出字母添加到list集合中,大小写紧挨着
  8. List<Character> list = new ArrayList<>();
  9. for (int i = 'A'; i <= 'Z'; i++) {
  10. for (int j = 0; j < str.length(); j++) {
  11. char c = str.charAt(j);
  12. if (c == i || c == i + 32) { // 该字母的大写或小写
  13. list.add(c);
  14. }
  15. }
  16. }
  17. // 2. 遍历字符串,找到非字母字符,插入到list 集合对应位置
  18. for (int i = 0; i < str.length(); i++) {
  19. char c = str.charAt(i);
  20. if (! Character.isLetter(c)) {
  21. list.add(i, c);
  22. }
  23. }
  24. // 3. list集合转字符串
  25. StringBuilder sb = new StringBuilder(str.length());
  26. for(Character c : list){
  27. sb.append(c);
  28. }
  29. System.out.println(sb);
  30. }
  31. }
  32. }

HJ27 查找兄弟单词

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. // 1. 前期处理,读取各项数据
  7. int N = scan.nextInt();
  8. String[] str = new String[N];
  9. for (int i = 0; i < N; i++) { // 输入n个单词作为字典单词
  10. str[i] = scan.next();
  11. }
  12. String findStr = scan.next(); // 输入一个待查单词
  13. int count = scan.nextInt(); // 输入待查单词的 指定序号
  14. // 2. 查找兄弟单词
  15. ArrayList<String> list = new ArrayList<>();
  16. for (int i = 0; i < N; i++) {
  17. // 长度相等,且字面值不相等
  18. if ((str[i].length() == findStr.length()) && (!str[i].equals(findStr))) {
  19. if (checkBorther(findStr, str[i])) {
  20. list.add(str[i]);
  21. }
  22. }
  23. }
  24. // 3. 输出
  25. Collections.sort(list);
  26. System.out.println(list.size());
  27. if (list.size() >= count) {
  28. System.out.println(list.get(count - 1));
  29. }
  30. }
  31. }
  32. // 判断两个字符串是否是兄弟单词
  33. public static boolean checkBorther(String str1, String str2) {
  34. // 桶排序思想
  35. int[] flag = new int[26];
  36. char[] ch1 = str1.toCharArray();
  37. char[] ch2 = str2.toCharArray();
  38. for (int i = 0; i < ch1.length; i++) {
  39. flag[ch1[i] - 'a']++;
  40. flag[ch2[i] - 'a']--;
  41. }
  42. for (int i = 0; i < 26; i++) {
  43. if (flag[i] != 0) {
  44. return false;
  45. }
  46. }
  47. return true;
  48. }
  49. }


HJ28 素数伴侣

方法1:匈牙利配对法

  1. import java.util.*;
  2. public class Main {
  3. // 方法1:
  4. public static void main(String[] args) throws Exception {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. // 1. 读取数据
  8. int count = scan.nextInt();
  9. int[] arr = new int[count];
  10. for (int i = 0; i < count; i++) {
  11. arr[i] = scan.nextInt();
  12. }
  13. // 2. 元素奇偶分开
  14. ArrayList<Integer> evens = new ArrayList<>();
  15. ArrayList<Integer> odds = new ArrayList<>();
  16. for (int i = 0; i < count; i++) {
  17. if (arr[i] % 2 == 1) {
  18. odds.add(arr[i]);
  19. } else {
  20. evens.add(arr[i]);
  21. }
  22. }
  23. // 3. 奇偶配对 匈牙利配对法
  24. int result = 0;
  25. // 记录偶数配对的奇数伴侣的index(基1)
  26. int[] eventPairs = new int[evens.size() ];
  27. for (int i = 0; i < odds.size(); i++) {
  28. boolean[] used = new boolean[evens.size()];
  29. if (findPair(i, odds, evens, eventPairs, used)) {
  30. result++;
  31. }
  32. }
  33. System.out.println(result);
  34. }
  35. }
  36. public static boolean findPair(int oddIndex, ArrayList<Integer> odds, ArrayList<Integer> evens, int[] eventPairs, boolean[] used) {
  37. for (int i = 0; i < evens.size(); i++) {
  38. // 该偶数没有被使用过,且符合匹配规则
  39. if (!used[i] && isPrime(odds.get(oddIndex) + evens.get(i) )) {
  40. used[i] = true;
  41. if (eventPairs[i] == 0 || findPair(eventPairs[i] - 1, odds, evens, eventPairs, used)) {
  42. eventPairs[i] = oddIndex + 1;
  43. return true;
  44. }
  45. }
  46. }
  47. return false;
  48. }
  49. // 判断是否为素数
  50. public static boolean isPrime(int num) {
  51. // 1. 特殊情况 2,3
  52. if (num <= 3) {
  53. return num > 1;
  54. }
  55. // 2. 只有每个6X-1 和 6X+1可能为质数
  56. if (num % 6 != 1 && num % 6 != 5) {
  57. return false;
  58. }
  59. double sqrt = Math.sqrt(num);
  60. // 判断每个 6X-1 和 6X+1
  61. for (int i = 5; i < sqrt; i += 6) {
  62. if (num % i == 0 || num % (i + 2) == 0) {
  63. return false;
  64. }
  65. }
  66. return true;
  67. }
  68. }

HJ29 字符串加解密

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. System.out.println(encode(scan.nextLine()));
  7. System.out.println(decode(scan.nextLine()));
  8. }
  9. }
  10. // 加密函数
  11. private static String encode(String code) {
  12. char[] arr = code.toCharArray();
  13. for (int i = 0; i < arr.length; i++) {
  14. if (arr[i] >= 'a' && arr[i] < 'z')
  15. arr[i] = (char) (arr[i] - 'a' + 'A' + 1);
  16. else if (arr[i] == 'z')
  17. arr[i] = 'A';
  18. else if (arr[i] >= 'A' && arr[i] < 'Z')
  19. arr[i] = (char) (arr[i] - 'A' + 'a' + 1);
  20. else if (arr[i] == 'Z')
  21. arr[i] = 'a';
  22. else if (arr[i] >= '0' && arr[i] < '9')
  23. arr[i] = (char) (arr[i] + 1);
  24. else if (arr[i] == '9')
  25. arr[i] = '0';
  26. }
  27. return String.valueOf(arr);
  28. }
  29. // 解密函数
  30. private static String decode(String password) {
  31. char[] arr = password.toCharArray();
  32. for (int i = 0; i < arr.length; i++) {
  33. if (arr[i] > 'a' && arr[i] <= 'z')
  34. arr[i] = (char) (arr[i] - 'a' + 'A' - 1);
  35. else if (arr[i] == 'a')
  36. arr[i] = 'Z';
  37. else if (arr[i] > 'A' && arr[i] <= 'Z')
  38. arr[i] = (char) (arr[i] - 'A' + 'a' - 1);
  39. else if (arr[i] == 'A')
  40. arr[i] = 'z';
  41. else if (arr[i] > '0' && arr[i] <= '9')
  42. arr[i] = (char) (arr[i] - 1);
  43. else if (arr[i] == '0')
  44. arr[i] = '9';
  45. }
  46. return String.valueOf(arr);
  47. }
  48. }

HJ31 单词倒排

方法1:正则表达式分割

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. String res = reverse(str);
  8. System.out.println(res);
  9. }
  10. }
  11. public static String reverse(String str) {
  12. // 正则表达式匹配非字母的字符
  13. String[] arr = str.split("[^A-Za-z]");
  14. StringBuilder sb = new StringBuilder();
  15. // 逆序添加
  16. for (int i = arr.length - 1; i >= 0; i--) {
  17. sb.append(arr[i]).append(" ");
  18. }
  19. return sb.toString().trim();
  20. }
  21. }

HJ33 整数与IP地址间的转换

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.next();
  7. String res;
  8. if (str.contains(".")) {
  9. res = ip2num(str);
  10. } else {
  11. res = num2ip(str);
  12. }
  13. System.out.println(res);
  14. }
  15. }
  16. // IP转数字,注意进制转化
  17. private static String ip2num(String str) {
  18. String[] arr = str.split("\\.");
  19. long result = 0;
  20. for (int i = 0; i < 4; i++) {
  21. result = result * 256 + Integer.parseInt(arr[i]);
  22. System.out.println(result);
  23. }
  24. return "" + result;
  25. }
  26. // 数字转IP,注意字符串拼接顺序
  27. private static String num2ip(String str) {
  28. long ipv4 = Long.parseLong(str);
  29. String res = "";
  30. for (int i = 0; i < 4; i++) {
  31. int num = (int) (ipv4 % 256);
  32. res = num + "." + res;
  33. ipv4 /= 256;
  34. }
  35. return res.substring(0, res.length() - 1);
  36. }
  37. }

HJ34 图片整理

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int bucket[] = new int[128];
  7. String str = scan.next();
  8. // 1. 字符映射数组的下标
  9. for (int i = 0; i < str.length(); i++) {
  10. char c = str.charAt(i);
  11. bucket[c]++;
  12. }
  13. // 2. 打印
  14. for (int i = 48; i < bucket.length; i++) { // 从'0'开始输出
  15. if (bucket[i] != 0) {
  16. for (int j = 0; j < bucket[i]; j++) {
  17. System.out.print((char) i);
  18. }
  19. }
  20. }
  21. System.out.println();
  22. }
  23. }
  24. }

HJ35 三角矩阵

方法1:总结出数列规律。

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. StringBuilder sb = new StringBuilder();
  8. for (int row = 1; row <= n; row++) {
  9. // 1. 按行处理,元素为 (j * j + j) / 2
  10. for (int j = 1; j < n - (row - 1); j++) {
  11. int num = (j + row - 1);
  12. int value = (num * num + num) / 2 - (row - 1);
  13. sb.append(value).append(" ");
  14. }
  15. // 2. 添加每行末尾的元素
  16. int end = (n * n + n) / 2 - (row - 1);
  17. sb.append(end).append("\n");
  18. }
  19. System.out.println(sb);
  20. }
  21. }
  22. }

HJ36 字符串加密

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String key = scan.next().toLowerCase();
  7. String s = scan.next();
  8. ArrayList<Character> list = new ArrayList<>();
  9. // 如果list中不存在就放入
  10. for (int i = 0; i < key.length(); i++) {
  11. if (!list.contains(key.charAt(i))) {
  12. list.add(key.charAt(i));
  13. }
  14. }
  15. // 将A-Z放入到list中
  16. for (int i = 97; i <= 122; i++) {
  17. char c = (char) i;
  18. if (!list.contains(c)) {
  19. list.add(c);
  20. }
  21. }
  22. Map<Character, Character> map = new HashMap<>();
  23. int begin = 97;
  24. for (int i = 0; i < list.size(); i++) {
  25. map.put((char) (begin + i), list.get(i));
  26. }
  27. StringBuilder sb = new StringBuilder();
  28. for (int i = 0; i < s.length(); i++) {
  29. char c = s.charAt(i);
  30. Character character = map.get(c);
  31. if (s.charAt(i) >= 97 && s.charAt(i) <= 122) {
  32. sb.append(character);
  33. } else {
  34. sb.append(Character.toUpperCase(character));
  35. }
  36. }
  37. System.out.println(sb.toString());
  38. }
  39. }
  40. }

HJ37 数兔子

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. System.out.println(countRabbit(n));
  8. }
  9. }
  10. public static int countRabbit(int n) {
  11. if (n == 1 || n == 2) {
  12. return 1;
  13. }
  14. return countRabbit(n - 1) + countRabbit(n - 2);
  15. }
  16. }

HJ38 小球落地反弹总路程

如图所示:假设从地面弹起到高度h,这样计算简单,最后再减去h就可以了。
image.png

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int h = scan.nextInt();
  7. double temp = h;
  8. double sum = 0;
  9. // 1. 假设小球从地上弹起到初始高度h,再落下来计算
  10. for (int i = 0; i < 5; i++) {
  11. sum += temp * 2;
  12. temp = temp / 2;
  13. }
  14. // 2. 减掉第一次假设弹上来的高度h
  15. sum -= h;
  16. System.out.printf("%.6f\n", sum);
  17. System.out.printf("%.6f\n", temp);
  18. }
  19. }
  20. }

HJ40 统计四种字符个数

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. int letters = 0;
  8. int spaces = 0;
  9. int digits = 0;
  10. int others = 0;
  11. for (int i = 0; i < str.length(); i++) {
  12. char c = str.charAt(i);
  13. if (Character.isLetter(c)) {
  14. letters++;
  15. } else if (Character.isDigit(c)) {
  16. digits++;
  17. } else if (Character.isSpaceChar(c)) {
  18. spaces++;
  19. } else {
  20. others++;
  21. }
  22. }
  23. System.out.println(letters);
  24. System.out.println(spaces);
  25. System.out.println(digits);
  26. System.out.println(others);
  27. }
  28. }
  29. }

HJ41 砝码可称量的重量

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. int[] weight = new int[n];
  8. int[] nums = new int[n];
  9. for (int i = 0; i < n; i++) {
  10. weight[i] = scan.nextInt();
  11. }
  12. for (int i = 0; i < n; i++) {
  13. nums[i] = scan.nextInt();
  14. }
  15. int count = fama(n, weight, nums);
  16. System.out.println(count);
  17. }
  18. scan.close();
  19. }
  20. public static int fama(int n, int[] weight, int[] nums) {
  21. // 1. 先往set中添加第一个砝码可称量出来的重量
  22. Set<Integer> set = new HashSet<>();
  23. for (int i = 0; i <= nums[0]; i++) {
  24. set.add(weight[0] * i);
  25. }
  26. // 2. 遍历其他砝码,得到当前这个型号的砝码可称量的重量,添加到set中
  27. for (int i = 1; i < n; i++) {
  28. List<Integer> list = new ArrayList<>(set);
  29. for (int j = 0; j <= nums[i]; j++) {
  30. // 遍历上一刻的集合,把新的重量添加进去
  31. for (int k = 0; k < list.size(); k++) {
  32. int newWeight = weight[i] * j;
  33. set.add(list.get(k) + newWeight);
  34. }
  35. }
  36. }
  37. return set.size();
  38. }
  39. }

HJ43 迷宫问题

描述:定义一个二维数组 N*M ,如 5 × 5 数组下所示:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。
本题含有多组数据,输入的内容只包含0~1

输入描述:输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

输出描述:
左上角到右下角的最短路径,格式如样例所示。

迷宫的例子

  1. int[][] maze = {
  2. {0, 1, 0, 0, 0},
  3. {0, 1, 1, 1, 0},
  4. {0, 0, 0, 0, 0},
  5. {0, 1, 1, 1, 0},
  6. {0, 0, 0, 1, 0}
  7. };

image.png

方法1:回溯算法。
思考:下图就是代码的运行轨迹,要多在脑海中想象。
华为迷宫问题DFS路径探索Snipaste.png

这是在某个位置,当四个方向上遍历结束时,打印当前path里面存储的路径结点。

  1. 当前坐标:[3 ,4] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)-->(2,4)-->(3,4)-->(4,4)
  2. 当前坐标:[0 ,2] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)-->(2,4)-->(3,4)-->(1,4)-->(0,4)-->(0,3)-->(0,2)
  3. 当前坐标:[0 ,3] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)-->(2,4)-->(3,4)-->(1,4)-->(0,4)-->(0,3)
  4. 当前坐标:[0 ,4] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)-->(2,4)-->(3,4)-->(1,4)-->(0,4)
  5. 当前坐标:[1 ,4] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)-->(2,4)-->(3,4)-->(1,4)
  6. 当前坐标:[2 ,4] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)-->(2,4)-->(3,4)
  7. 当前坐标:[2 ,3] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)-->(2,4)
  8. 当前坐标:[2 ,2] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)-->(2,3)
  9. 当前坐标:[2 ,1] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(2,2)
  10. 当前坐标:[4 ,2] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(3,0)-->(4,0)-->(4,1)-->(4,2)
  11. 当前坐标:[4 ,1] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(3,0)-->(4,0)-->(4,1)
  12. 当前坐标:[4 ,0] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(3,0)-->(4,0)
  13. 当前坐标:[3 ,0] (0,0)-->(1,0)-->(2,0)-->(2,1)-->(3,0)
  14. 当前坐标:[2 ,0] (0,0)-->(1,0)-->(2,0)-->(2,1)
  15. 当前坐标:[1 ,0] (0,0)-->(1,0)-->(2,0)
  16. 当前坐标:[0 ,0] (0,0)-->(1,0)
  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. int m = scan.nextInt();
  8. // 1. 创建迷宫数组,从控制台读取数据并初始化数组
  9. int[][] maze = new int[n][m];
  10. for (int i = 0; i < n; i++) {
  11. for (int j = 0; j < m; j++) {
  12. maze[i][j] = scan.nextInt();
  13. }
  14. }
  15. // 2. 创建两个list,分别存储一条路径和所有路径
  16. ArrayList<int[]> path = new ArrayList<>();
  17. ArrayList<ArrayList<int[]>> ret = new ArrayList<>();
  18. // 3. DFS,深度优先搜索
  19. dfsMazePath(maze, 0, 0, path, ret);
  20. // 4. 找到结果集中最短的路径
  21. int minIndex = 0;
  22. for (int i = 0; i < ret.size(); i++) {
  23. if (ret.get(i).size() < ret.get(minIndex).size()) {
  24. minIndex = i;
  25. }
  26. }
  27. // 5. 按题目要求打印路径
  28. path = ret.get(minIndex);
  29. for (int i = 0; i < path.size(); i++) {
  30. int[] arr = path.get(i);
  31. System.out.println("(" + arr[0] + "," + arr[1] + ")");
  32. }
  33. }
  34. }
  35. public static void dfsMazePath(int[][] maze, int i, int j, ArrayList<int[]> path, ArrayList<ArrayList<int[]>> ret) {
  36. // 1. 递归的终止条件:边界
  37. if (i < 0 || i > maze.length - 1 || j < 0 || j > maze[0].length - 1) {
  38. return;
  39. }
  40. // 2. 递归的终止条件:当前路径不可走,返回
  41. if (maze[i][j] == 1) {
  42. return;
  43. }
  44. // 3. 递归的终止条件:到达迷宫的终点
  45. if (i == maze.length - 1 && j == maze[0].length - 1) {
  46. int[] last = {i, j};
  47. path.add(last);
  48. ret.add(new ArrayList<>(path));
  49. return;
  50. }
  51. // 4. 当前路径可走,添加到path中,并把坐标设置为不可访问
  52. int[] cur = {i, j};
  53. path.add(cur);
  54. maze[i][j] = 1;
  55. // 5. 向四个方向进行探索
  56. dfsMazePath(maze, i, j + 1, path, ret); // 右
  57. dfsMazePath(maze, i + 1, j, path, ret); // 下
  58. dfsMazePath(maze, i, j - 1, path, ret); // 左
  59. dfsMazePath(maze, i - 1, j, path, ret); // 上
  60. // // 这段代码主要是用来查看DFS遍历的轨迹
  61. // System.out.print("当前坐标:" + "[" + i + " ," + j + "] ");
  62. // for (int k = 0; k < path.size(); k++) {
  63. // int[] tmp = path.get(k);
  64. // System.out.print("(" + tmp[0] + "," + tmp[1] + ")");
  65. // if (k != path.size() - 1) {
  66. // System.out.print("-->");
  67. // }
  68. // }
  69. // System.out.println();
  70. // 6. 回溯。path中移除最后一个坐标,并把当前坐标恢复成可访问
  71. path.remove(path.size() - 1);
  72. maze[i][j] = 0;
  73. }
  74. }

HJ52 编辑距离

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str1 = scan.nextLine();
  7. String str2 = scan.nextLine();
  8. int m = str1.length();
  9. int n = str2.length();
  10. // 1. 创建dp数组,并初始化边缘状态
  11. int[][] dp = new int[m + 1][n + 1];
  12. dp[0][0] = 0;
  13. for (int i = 1; i < dp.length; i++) {
  14. dp[i][0] = i;
  15. }
  16. for (int i = 1; i < dp[0].length; i++) {
  17. dp[0][i] = i;
  18. }
  19. // 2. 填充dp数组
  20. for (int i = 1; i < dp.length; i++) {
  21. for (int j = 1; j < dp[0].length; j++) {
  22. if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
  23. dp[i][j] = dp[i - 1][j - 1];
  24. } else {
  25. int insertCost = dp[i][j - 1] + 1;
  26. int deleteCost = dp[i - 1][j] + 1;
  27. int replaceCost = dp[i - 1][j - 1] + 1;
  28. dp[i][j] = Math.min(insertCost, Math.min(deleteCost, replaceCost));
  29. }
  30. }
  31. }
  32. System.out.println(dp[m][n]);
  33. }
  34. }
  35. }

HJ53 杨辉三角的变形

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNextInt()) {
  6. int num = scan.nextInt();
  7. if (num == 1 || num == 2) {
  8. System.out.println(-1);
  9. } else if (num % 4 == 1 || num % 4 == 3) {
  10. System.out.println(2);
  11. } else if (num % 4 == 0) {
  12. System.out.println(3);
  13. } else if (num % 4 == 2) {
  14. System.out.println(4);
  15. }
  16. }
  17. }
  18. }

HJ54 表达式求值

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. String s = scan.nextLine();
  6. s = s.replace("{", "(");
  7. s = s.replace("[", "(");
  8. s = s.replace("}", ")");
  9. s = s.replace("]", ")");
  10. System.out.println(slove(s));
  11. }
  12. public static int slove(String s) {
  13. int len = s.length();
  14. char[] arr = s.toCharArray();
  15. int index = 0;
  16. char sign = '+';
  17. int number = 0;
  18. Stack<Integer> stack = new Stack<>();
  19. // 遍历字符串
  20. for (int i = 0; i < len; i++) {
  21. char ch = arr[i];
  22. // 1. 当前字符是空格,跳过
  23. if (ch == ' ') {
  24. continue;
  25. }
  26. // 2. 当前字符是数字,拼接数字
  27. if (Character.isDigit(ch)) {
  28. number = number * 10 + ch - '0';
  29. }
  30. // 3. 当前字符是小括号
  31. if (ch == '(') {
  32. int j = i + 1;
  33. int count = 1;
  34. while (count > 0) {
  35. if (arr[j] == ')') {
  36. count--;
  37. }
  38. if (arr[j] == '(') {
  39. count++;
  40. }
  41. j++;
  42. }
  43. // 递归,解小括号中的表达式
  44. number = slove(s.substring(i + 1, j - 1));
  45. i = j - 1;
  46. }
  47. // 4. 遇到符号,将数字处理后放进栈
  48. if (!Character.isDigit(ch) || i == len - 1) {
  49. if (sign == '+') {
  50. stack.push(number);
  51. } else if (sign == '-') {
  52. stack.push(-1 * number);
  53. } else if (sign == '*') {
  54. stack.push(stack.pop() * number);
  55. } else if (sign == '/') {
  56. stack.push(stack.pop() / number);
  57. }
  58. sign = ch;
  59. number = 0;
  60. }
  61. }
  62. // 5. 栈中数字求和得到结果
  63. int ans = 0;
  64. while (!stack.isEmpty()) {
  65. ans += stack.pop();
  66. }
  67. return ans;
  68. }
  69. }

HJ55 挑7

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. int count = 0;
  8. for (int i = 1; i <= n; i++) {
  9. if (i % 7 == 0) {
  10. count++;
  11. } else {
  12. String s = String.valueOf(i);
  13. if (s.contains("7")) {
  14. count++;
  15. }
  16. }
  17. }
  18. System.out.println(count);
  19. }
  20. }
  21. }

HJ56 完全数计算

  1. import java.util.*;
  2. public class Main {
  3. // 参考:https://blog.nowcoder.net/n/9d96f4ca947f493b8c7632cddfd9cb24
  4. public static void main(String[] args) {
  5. Scanner scan = new Scanner(System.in);
  6. while (scan.hasNext()) {
  7. int num = scan.nextInt();
  8. int count = 0;
  9. for (int i = 2; i <= num; i++) {
  10. if (isPerfect(i)) {
  11. count++;
  12. }
  13. }
  14. System.out.println(count);
  15. }
  16. }
  17. public static boolean isPerfect(int n) {
  18. // 每个数都有因子 1
  19. int sum = 1;
  20. // 数学原理:一对因子总会分布在这个数的根号两边,或者就是这平方根值。
  21. for (int i = 2; i * i <= n; i++) {
  22. // 如果能被整除
  23. if (n % i == 0) {
  24. int quotient = n / i; // 整除得到的商
  25. if (quotient == i) { // 商和除数一样
  26. sum = sum + i;
  27. } else {
  28. sum = sum + i + quotient; // 不为平方根时,加上两个因子
  29. }
  30. }
  31. }
  32. return sum == n;
  33. }
  34. }

HJ60 查找组成一个偶数最接近的两个素数

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. // 最接近的素数,就从数的中间开始
  8. for (int i = n / 2; i >= 2; i--) {
  9. if (isPrime(i) && isPrime(n - i)) {
  10. System.out.println(i);
  11. System.out.println(n - i);
  12. break;
  13. }
  14. }
  15. }
  16. }
  17. public static boolean isPrime(int n) {
  18. // 素数 除了1和它本身的数,都不能被整除,所以要从2 开始到小于n
  19. for (int i = 2; i < n; i++) {
  20. if (n % i == 0) {
  21. return false;
  22. }
  23. }
  24. return true;
  25. }
  26. }

HJ62 二进制中1的个数

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. int count = 0;
  8. while (n != 0) {
  9. n = n & (n - 1);
  10. count++;
  11. }
  12. System.out.println(count);
  13. }
  14. }
  15. }

HJ63 DNA序列

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. int n = scan.nextInt();
  8. double len = 0.0;
  9. String result = "";
  10. for (int i = 0; i < str.length() - n + 1; i++) {
  11. String aim = str.substring(i, i + n);
  12. String res = aim.replaceAll("[^CG]", "");
  13. double cur = (double) res.length() / (double) n;
  14. if (cur > len) {
  15. len = cur;
  16. result = aim;
  17. }
  18. }
  19. System.out.println(result);
  20. }
  21. }
  22. }

HJ65 最长公共子串

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String s1 = scan.nextLine();
  7. String s2 = scan.nextLine();
  8. // 题目要求特殊:输出在较短串中最先出现的那个
  9. String temp = "";
  10. if (s1.length() > s2.length()) {
  11. temp = s1;
  12. s1 = s2;
  13. s2 = temp;
  14. }
  15. System.out.println(lcs(s1, s2));
  16. }
  17. }
  18. // 动态规划
  19. public static String lcs(String str1, String str2) {
  20. int m = str1.length();
  21. int n = str2.length();
  22. // 1. 创建dp数组
  23. // dp[i][j] 表示以str1第i个字符结尾,同时在str2中第j 个字符结尾时的公共子串长度
  24. int[][] dp = new int[m + 1][n + 1];
  25. int maxLen = 0;
  26. int end = 0;
  27. // 2. 填充dp数组
  28. for (int i = 1; i <= m; i++) {
  29. for (int j = 1; j <= n; j++) {
  30. // 3. 从头开始比较两个字符串,
  31. // 如果当前两个字符相同,长度就在上一个基础上加1
  32. // 如果不相同,公共子串就断开了,dp[i][j] = 0,因为初始化默认是0,所以不用重新赋值
  33. if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
  34. dp[i][j] = dp[i - 1][j - 1] + 1;
  35. // 4. 更新记录最大的长度
  36. if (dp[i][j] > maxLen) {
  37. maxLen = dp[i][j];
  38. // end 记录最长公共子串尾部字符的索引坐标
  39. end = i - 1;
  40. }
  41. }
  42. }
  43. }
  44. // 5. 截取最长公共子串,[end - maxLen + 1, end + 1)
  45. return str1.substring(end - maxLen + 1, end + 1);
  46. }
  47. }

HJ67 24点

这个题有点意思,原来还是用DFS来做的,有想过打印出一个完整的算式,但做了半天没做出来,以后再看看吧。

  1. import java.util.*;
  2. public class Main {
  3. // 全局变量
  4. static boolean flag = false;
  5. public static void main(String[] args) {
  6. Scanner scan = new Scanner(System.in);
  7. while (scan.hasNext()) {
  8. String[] s = scan.nextLine().split(" ");
  9. int[] arr = new int[4];
  10. boolean[] visit = new boolean[4];
  11. for (int i = 0; i < 4; i++) {
  12. arr[i] = Integer.parseInt(s[i]);
  13. }
  14. dfs(arr, 0, 0, visit);
  15. System.out.println(flag);
  16. }
  17. }
  18. private static boolean dfs(int[] arr, int count, float num, boolean[] visit) {
  19. if (count == 4 && num == 24) {
  20. flag = true;
  21. return true;
  22. }
  23. for (int i = 0; i < 4; i++) {
  24. if (visit[i] == false) {
  25. visit[i] = true;
  26. if (dfs(arr, count + 1, num + arr[i], visit) ||
  27. dfs(arr, count + 1, num - arr[i], visit) ||
  28. dfs(arr, count + 1, num * arr[i], visit) ||
  29. dfs(arr, count + 1, num / arr[i], visit)) {
  30. return true;
  31. }
  32. visit[i] = false;
  33. }
  34. }
  35. return false;
  36. }
  37. }

HJ72 百钱买百鸡问题

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. // 鸡翁值5, 一百块最多买20只 鸡翁买x只
  5. // 鸡母值3, 一百块最多买33只 鸡母买y只
  6. // 鸡雏三值1, 一百块最多买300只 鸡雏买z只
  7. Scanner scan = new Scanner(System.in);
  8. // 买x鸡翁,y只鸡母,z只鸡雏
  9. // 5x + 3y + z/3 = 100 ==> 15x + 9y + z = 300
  10. // x + y + z = 100 加上面式子 ==> 14x + 8y = 200 ==> 7x + 4y = 100 ==> y = (100 - 7x)/4
  11. while (scan.hasNextInt()) {
  12. int n = scan.nextInt();
  13. for (int x = 0; x <= 14; x++) {
  14. if ((100 - 7 * x) % 4 == 0) {
  15. int y = (100 - 7 * x) / 4;
  16. int z = 100 - x - y;
  17. System.out.println(x + " " + y + " " + z);
  18. }
  19. }
  20. }
  21. }
  22. }

HJ76 尼科彻斯定理

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNextInt()) {
  6. int num = scan.nextInt();
  7. long sum = (long) Math.pow(num, 3);
  8. int a1 = (int) sum / num - (num - 1);
  9. StringBuilder sb = new StringBuilder();
  10. sb.append(a1);
  11. for (int i = 1; i < num; i++) {
  12. a1 = a1 + 2;
  13. sb.append("+");
  14. sb.append(a1);
  15. }
  16. System.out.println(sb);
  17. }
  18. }
  19. }

HJ77 火车进站

题目没看懂,代码也只是大概看了下。

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. int n = scan.nextInt();
  7. // 未进站的火车
  8. Queue<Integer> queue = new LinkedList<>();
  9. // 已进站的火车
  10. Stack<Integer> stack = new Stack<>();
  11. for (int i = 0; i < n; i++) {
  12. queue.offer(scan.nextInt());
  13. }
  14. List<String> outQueueList = new ArrayList<>();
  15. // 获取所有出站队列保存到outQueueList
  16. processOutQueue(queue, stack, "", outQueueList);
  17. // 排序后输出
  18. Collections.sort(outQueueList);
  19. for (String str : outQueueList) {
  20. System.out.println(str);
  21. }
  22. }
  23. }
  24. private static void processOutQueue(Queue<Integer> queue, Stack<Integer> stack, String outQueue, List<String> list) {
  25. // 1. 递归的终止条件:如果队列和栈都为空,则保存出站信息
  26. if (queue.isEmpty() && stack.isEmpty()) {
  27. list.add(outQueue.trim());
  28. return;
  29. }
  30. // 2. 出栈
  31. if (!stack.isEmpty()) {
  32. // 先克隆
  33. Queue<Integer> tempQueue = new LinkedList<>(queue);
  34. Stack<Integer> tempStack = (Stack<Integer>) stack.clone();
  35. String tempOutQueue = outQueue + (tempStack.pop() + " ");
  36. processOutQueue(tempQueue, tempStack, tempOutQueue, list);
  37. }
  38. // 3. 队列入队
  39. if (!queue.isEmpty()) {
  40. // 先克隆
  41. Queue<Integer> tempQueue = new LinkedList<>(queue);
  42. Stack<Integer> tempStack = (Stack<Integer>) stack.clone();
  43. tempStack.push(tempQueue.poll());
  44. processOutQueue(tempQueue, tempStack, outQueue, list);
  45. }
  46. }
  47. }

HJ84 统计大写字母个数

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String str = scan.nextLine();
  7. // 使用正则表达式特别方便,这句代码意思是把所有非大写字母替换为空
  8. String res = str.replaceAll("[^A-Z]", "");
  9. System.out.println(res.length());
  10. }
  11. }
  12. }

HJ86 二进制中最长连续1

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNextInt()) {
  6. int num = scan.nextInt();
  7. int maxLen = 0;
  8. int count = 0;
  9. while (num != 0) {
  10. // 1. 当前二进制数字末尾是1,和1做&运算,会得到1
  11. if ((num & 1) == 1) {
  12. count++;
  13. maxLen = Math.max(maxLen, count);
  14. } else {
  15. // 2. 当前二进制是0,就把cont重新设置为0
  16. count = 0;
  17. }
  18. // 3. 无符号右移
  19. num >>>= 1;
  20. }
  21. System.out.println(maxLen);
  22. }
  23. }
  24. }

HJ92 连续最长的数字串

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner sc = new Scanner(System.in);
  5. while (sc.hasNextLine()) {
  6. String str = sc.nextLine();
  7. int len = str.length();
  8. int[] dp = new int[len + 1];
  9. int maxLen = 0;
  10. for (int i = 1; i <= len; i++) {
  11. char c = str.charAt(i - 1);
  12. if (c >= '0' && c <= '9') {
  13. dp[i] = dp[i - 1] + 1;
  14. maxLen = Math.max(maxLen, dp[i]);
  15. }
  16. }
  17. for (int i = 1; i <= len; i++) {
  18. if (dp[i] == maxLen) {
  19. System.out.print(str.substring(i - maxLen, i));
  20. }
  21. }
  22. System.out.println("," + maxLen);
  23. }
  24. }
  25. }

HJ96 数字首尾加符号

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner scan = new Scanner(System.in);
  5. while (scan.hasNext()) {
  6. String input = scan.next();
  7. String str = input.replaceAll("([0-9]+)", "*$1*");
  8. System.out.println(str);
  9. }
  10. }
  11. }