一、前言
总结三次题目集的知识点、题量、难度等情况
第一次PTA作业:
- 变量的定义和使用
- 标准输入输出
- 条件语句的使用
- 算术运算符和比较运算符的使用
题量为9,难度适中。
第二次PTA作业:
- 类和对象的定义和使用
- 数组的定义和使用
- 标准输入输出
- 条件语句和循环语句的使用
- 字符串的处理
- 日期计算
- 动态规划
题量为4,难度偏难。
第三次PTA作业:
- 类和对象的定义和使用
- 数组的定义和使用
- 字符串的处理
- 标准输入输出
- 条件语句和循环语句的使用
- 日期计算
- 集合类的使用
- 排序算法
题量为7,难度偏难。
二、设计与分析
第一次PTA作业:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 double w,h,BMI; 6 Scanner in = new Scanner(System.in); 7 w = in.nextDouble(); 8 h = in.nextDouble(); 9 BMI = w/h/h; 10 if(w<=0||h<=0||w>727||h>2.72) { 11 System.out.print("input out of range"); 12 } 13 else{ 14 if(BMI<18.5) { 15 System.out.print("thin"); 16 } 17 if(BMI<24&&BMI>=18.5) { 18 System.out.print("fit"); 19 } 20 if(BMI<28&&BMI>=24) { 21 System.out.print("overweight"); 22 } 23 if(BMI>=28) { 24 System.out.print("fat"); 25 } 26 } 27 } 28 }
这段代码先计算并输出用户的BMI值。首先,程序创建了一个Scanner对象来读取用户输入的体重(w)和身高(h)。然后,程序使用公式 BMI = w/h/h 计算BMI值。接下来,程序检查输入值是否在有效范围内。如果输入值超出范围,程序将输出“input out of range”。否则,程序将根据BMI值输出用户的身体状况(thin, fit, overweight, fat)。
1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 double b,c,w,m; 7 Scanner in = new Scanner(System.in); 8 c = in.nextDouble(); 9 b = in.nextDouble(); 10 w = c/0.45359237; 11 m = b/0.0254; 12 System.out.print((float)w+" "+(float)m); 13 } 14 15 }
这段代码将用户输入的重量和身高从公制单位转换为英制单位。首先,程序创建了一个Scanner对象来读取用户输入的重量(c)和身高(b)。然后,程序使用公式 w = c/0.45359237 和 m = b/0.0254 将重量和身高分别转换为磅和英寸。最后,程序输出转换后的重量和身高。(因为第一次作业知识点都差不多,故此分析两题作为代表)
第二次PTA作业:
1 import java.util.HashMap; 2 import java.util.Map; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 Scanner input = new Scanner(System.in); 8 Map<String, int[]> menu = new HashMap<>(); 9 menu.put("西红柿炒蛋", new int[]{15, 23, 30}); 10 menu.put("清炒土豆丝", new int[]{12, 18, 24}); 11 menu.put("麻婆豆腐", new int[]{12, 18, 24}); 12 menu.put("油淋生菜", new int[]{9, 14, 18}); 13 14 String dish; 15 int totalCost = 0; 16 while (true) { 17 dish = input.next(); 18 if (dish.equals("end")) break; 19 int size = input.nextInt(); 20 if (menu.containsKey(dish)) { 21 totalCost += menu.get(dish)[size - 1]; 22 } else { 23 System.out.println(dish + " does not exist"); 24 } 25 } 26 System.out.println(totalCost); 27 } 28 }
这段代码计算用户点菜的总价格。首先,程序创建了一个Scanner对象来读取用户输入。然后,程序使用一个HashMap来存储菜单,其中键是菜名,值是一个整数数组,表示不同大小的菜品的价格。接下来,程序进入一个循环,读取用户输入的菜名和大小。如果输入的菜名为“end”,则退出循环。否则,程序检查菜单中是否存在该菜名。如果存在,则将该菜品的价格累加到总价格中。如果不存在,则输出“菜名 does not exist”。最后,程序输出总价格。第一次的菜单计价程序比较简单,故简单分析。
1 import java.util.HashMap; 2 import java.util.Scanner; 3 4 public class Main { 5 public static void main(String[] args) { 6 Scanner input = new Scanner(System.in); 7 HashMap<String, Integer> menu = new HashMap<>(); 8 String A; 9 int B; 10 String C; 11 while (true) { 12 A = input.next(); 13 if (A.equals("1")) { 14 C = "1"; 15 break; 16 } 17 if (A.equals("end")) { 18 C = "0"; 19 break; 20 } 21 B = input.nextInt(); 22 menu.put(A, B); 23 } 24 int cnt = 0, sum = 0; 25 HashMap<Integer, Integer> recording = new HashMap<>(); 26 int re = 1; 27 String h = ""; 28 if (C.equals("1")) 29 while (!C.equals("end")) { 30 cnt = 0; 31 String dish = input.next(); 32 if (dish.equals("delete")) { 33 int p = Integer.parseInt(C); 34 if (!recording.containsKey(p)) System.out.println("delete error;"); 35 else { 36 sum -= recording.get(p); 37 recording.remove(p); 38 } 39 h = input.next(); 40 if (h.equals("end")) break; 41 if (!h.equals("end")) { 42 C = h; 43 continue; 44 } 45 } 46 int size1 = input.nextInt(); 47 int b = input.nextInt(); 48 49 if (!menu.containsKey(dish)) { 50 recording.put(re++, 0); 51 System.out.println(dish + " does not exist"); 52 } else { 53 int price = menu.get(dish); 54 switch (size1) { 55 case 1: 56 cnt += price; 57 break; 58 case 2: 59 cnt += Math.round(price * 1.5); 60 break; 61 case 3: 62 cnt += price * 2; 63 break; 64 } 65 cnt *= b; 66 sum += cnt; 67 recording.put(re++, cnt); 68 System.out.println(C + " " + dish + " " + cnt); 69 } 70 C = input.next(); 71 } 72 if (!C.equals("0")) 73 System.out.println(sum); 74 else System.out.println("0"); 75 } 76 }
这段代码允许用户输入菜单并计算点菜的总价格。首先,程序创建了一个Scanner对象来读取用户输入。然后,程序使用一个HashMap来存储菜单,其中键是菜名,值是价格。接下来,程序进入一个循环,读取用户输入的菜名和价格。如果输入的菜名为“1”或“end”,则退出循环。否则,程序将菜名和价格添加到菜单中。
在退出循环后,程序检查退出循环的原因。如果是因为输入了“1”,则继续读取用户输入的菜名、大小和数量,并根据菜单中的价格计算总价格。如果输入的菜名为“delete”,则删除指定的订单并更新总价格。如果菜单中不存在输入的菜名,则输出“菜名 does not exist”。最后,程序输出总价格。
类图如下

1 import java.time.LocalDate; 2 import java.time.temporal.ChronoUnit; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 Scanner scanner = new Scanner(System.in); 8 String firstDate = scanner.nextLine(); 9 String[] secondDates = scanner.nextLine().split(" "); 10 scanner.close(); 11 12 // Check if the first date is valid 13 if (isValidDate(firstDate)) { 14 LocalDate date = LocalDate.parse(firstDate); 15 if (isLeapYear(date.getYear())) { 16 System.out.println(firstDate + "是闰年."); 17 } 18 System.out.println(firstDate + "是当年第" + date.getDayOfYear() + "天,当月第" + date.getDayOfMonth() + "天,当周第" + date.getDayOfWeek().getValue() + "天."); 19 20 } else { 21 System.out.println(firstDate + "无效!"); 22 } 23 24 // Check if the second dates are valid 25 if (isValidDate(secondDates[0]) && isValidDate(secondDates[1])) { 26 LocalDate startDate = LocalDate.parse(secondDates[0]); 27 LocalDate endDate = LocalDate.parse(secondDates[1]); 28 29 if (endDate.isBefore(startDate)) { 30 System.out.print(endDate.toString() +"早于"+ startDate.toString() +",不合法!"); 31 return; 32 } 33 34 long daysBetween = ChronoUnit.DAYS.between(startDate, endDate); 35 long monthsBetween = endDate.getMonthValue()-startDate.getMonthValue(); 36 long yearsBetween = Math.abs(endDate.getYear()-startDate.getYear()); 37 38 System.out.print(endDate.toString()+ "与" + startDate.toString() + 39 "之间相差" + daysBetween + 40 "天,所在月份相差" + monthsBetween + 41 ",所在年份相差" + yearsBetween + 42 "."); 43 } else { 44 System.out.print(secondDates[0] +"或"+ secondDates[1] +"中有不合法的日期."); 45 } 46 } 47 48 private static boolean isValidDate(String dateString) { 49 try { 50 LocalDate.parse(dateString); 51 return true; 52 } catch (Exception e) { 53 return false; 54 } 55 } 56 57 private static boolean isLeapYear(int year) { 58 return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 59 } 60 }
这段代码读取用户输入的日期并进行一些计算和验证。首先,程序创建了一个Scanner对象来读取用户输入的第一个日期和第二个日期(用空格分隔)。然后,程序检查第一个日期是否有效。如果有效,则计算该日期是当年的第几天、当月的第几天和当周的第几天,并检查该年是否为闰年。如果无效,则输出“无效”。
接下来,程序检查第二个日期是否有效。如果有效,则计算两个日期之间相差的天数、月数和年数。如果无效,则输出“不合法”。
程序中定义了两个辅助方法:isValidDate用于检查日期字符串是否有效,isLeapYear用于检查给定的年份是否为闰年。
类图如下

1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 int m = sc.nextInt(); 7 while (m-- > 0) { 8 int n = sc.nextInt(); 9 int[] dp = new int[n + 1]; 10 dp[0] = 1; 11 for (int i = 1; i <= n; i++) { 12 for (int j = 1; j <= 4; j++) { 13 if (i - j >= 0) dp[i] += dp[i - j]; 14 } 15 } 16 System.out.println(dp[n]); 17 } 18 } 19 }
这段代码使用动态规划算法计算一个数学问题的解。首先,程序创建了一个Scanner对象来读取用户输入的测试用例数量m。然后,程序进入一个循环,每次循环读取一个整数n,并创建一个长度为n+1的数组dp来存储动态规划的结果。dp[i]表示当n=i时问题的解。
接下来,程序使用两层循环来计算dp数组。外层循环从1到n遍历i,内层循环从1到4遍历j。如果i-j>=0,则将dp[i-j]累加到dp[i]中。最后,程序输出dp[n],即当n=n时问题的解。
第三次PTA作业:
1 import java.util.*; 2 import java.text.*; 3 4 class Dish { 5 String name; 6 double price; 7 8 public Dish(String name, double price) { 9 this.name = name; 10 this.price = price; 11 } 12 } 13 14 class Order { 15 int tableNum; 16 Date time; 17 List<OrderItem> items = new ArrayList<>(); 18 List<OrderItem> deletedItems = new ArrayList<>(); 19 List<String> deleteErrors = new ArrayList<>(); 20 double discount; 21 boolean isOpen = true; 22 public Order(int tableNum, Date time) { 23 this.tableNum = tableNum; 24 this.time = time; 25 } 26 public boolean isOpen() { 27 Calendar cal = Calendar.getInstance(); 28 cal.setTime(time); 29 int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); 30 int hourOfDay = cal.get(Calendar.HOUR_OF_DAY); 31 int minuteOfHour = cal.get(Calendar.MINUTE); 32 if (dayOfWeek >= 2 && dayOfWeek <= 6) { 33 if ((hourOfDay == 10 && minuteOfHour >= 30) || (hourOfDay > 10 && hourOfDay < 14) || (hourOfDay == 14 && minuteOfHour <= 30)) { 34 discount = 0.6; 35 return true; 36 } else if ((hourOfDay == 17 && minuteOfHour >= 0) || (hourOfDay > 17 && hourOfDay < 20) || (hourOfDay == 20 && minuteOfHour <= 30)) { 37 discount = 0.8; 38 return true; 39 } else { 40 return false; 41 } 42 } else if (dayOfWeek == 1 || dayOfWeek == 7) { 43 if ((hourOfDay == 9 && minuteOfHour >= 30) || (hourOfDay > 9 && hourOfDay < 21) || (hourOfDay == 21 && minuteOfHour <= 30)) { 44 discount = 1.0; 45 return true; 46 } else { 47 return false; 48 } 49 } 50 return false; 51 } 52 public void addItem(OrderItem item) { 53 items.add(item); 54 } 55 56 public void removeItem(int index) { 57 if (index < 1 || index > items.size()) { 58 deleteErrors.add("delete error"); 59 return; 60 } 61 OrderItem item = items.get(index - 1); 62 deletedItems.add(item); 63 } 64 65 public int getTotalPrice() { 66 double totalPrice = 0.0; 67 for (OrderItem item : items) { 68 totalPrice += item.getTotalPrice(); 69 } 70 for (OrderItem item : deletedItems) { 71 totalPrice -= item.getTotalPrice(); 72 } 73 return (int) Math.round(totalPrice * discount); 74 } 75 } 76 77 class OrderItem { 78 int index; 79 String dishName; 80 int portion; 81 int quantity; 82 83 public OrderItem(int index, String dishName, int portion, int quantity) { 84 this.index = index; 85 this.dishName = dishName; 86 this.portion = portion; 87 this.quantity = quantity; 88 } 89 90 public int getTotalPrice() { 91 Dish dish = Menu.getDish(dishName); 92 if (dish == null) { 93 System.out.println(dishName + " does not exist"); 94 return 0; 95 } 96 double portionPriceFactor = 1.0; 97 if (portion == 2) { 98 portionPriceFactor = 1.5; 99 } else if (portion == 3) { 100 portionPriceFactor = 2.0; 101 } 102 return (int) Math.round(dish.price * portionPriceFactor * quantity); 103 } 104 } 105 106 class Menu { 107 static Map<String, Dish> dishes = new HashMap<>(); 108 109 public static void addDish(Dish dish) { 110 dishes.put(dish.name, dish); 111 } 112 113 public static Dish getDish(String name) { 114 return dishes.get(name); 115 } 116 } 117 118 public class Main { 119 120 public static void main(String[] args) throws ParseException { 121 122 Scanner scanner = new Scanner(System.in); 123 124 Map<Integer, Order> orders = new HashMap<>(); 125 126 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d H/m/s"); 127 128 Order currentOrder = null; 129 130 while (true) { 131 132 String line = scanner.nextLine(); 133 134 if (line.equals("end")) break; 135 136 String[] parts = line.split(" "); 137 138 if (parts[0].equals("table")) { 139 140 int tableNum = Integer.parseInt(parts[1]); 141 Date time = dateFormat.parse(parts[2] + " " + parts[3]); 142 currentOrder = new Order(tableNum, time); 143 orders.put(tableNum, currentOrder); 144 145 } else if (parts.length == 2 && parts[1].equals("delete")) { 146 147 int index = Integer.parseInt(parts[0]); 148 currentOrder.removeItem(index); 149 150 } else if (parts.length == 2) { 151 152 String dishName = parts[0]; 153 double price = Double.parseDouble(parts[1]); 154 Menu.addDish(new Dish(dishName, price)); 155 156 } else if (parts.length == 4) { 157 158 int index = Integer.parseInt(parts[0]); 159 String dishName = parts[1]; 160 int portion = Integer.parseInt(parts[2]); 161 int quantity = Integer.parseInt(parts[3]); 162 currentOrder.addItem(new OrderItem(index, dishName, portion, quantity)); 163 164 } else if (parts.length == 5) { 165 166 int tableNum = Integer.parseInt(parts[0]); 167 int index = Integer.parseInt(parts[1]); 168 String dishName = parts[2]; 169 int portion = Integer.parseInt(parts[3]); 170 int quantity = Integer.parseInt(parts[4]); 171 Order order = orders.get(tableNum); 172 if (order != null) { 173 order.addItem(new OrderItem(index, dishName, portion, quantity)); 174 } 175 176 } 177 178 } 179 int count = 0; 180 for (Order order : orders.values()) { 181 count++; 182 System.out.println("table " + order.tableNum + ": "); 183 for (OrderItem item : order.items) { 184 Dish dish = Menu.getDish(item.dishName); 185 if (dish == null) { 186 System.out.println(item.index + " " + item.dishName + " does not exist"); 187 } else { 188 System.out.println(item.index + " " + item.dishName + " " + item.getTotalPrice()); 189 } 190 } 191 for (String error : order.deleteErrors) { 192 System.out.println(error); 193 } 194 if (order.isOpen()) { 195 System.out.print("table " + order.tableNum + ": " + order.getTotalPrice()); 196 } else { 197 System.out.print("table " + order.tableNum + " out of opening hours"); 198 } 199 if (count < orders.size()) { 200 System.out.println(); 201 } 202 } 203 } 204 }
这段代码模拟了一个餐厅的点菜和结账过程。程序定义了四个类:Dish、Order、OrderItem和Menu。
Dish类表示菜品,包含菜名和价格两个属性。
Order类表示订单,包含桌号、时间、菜品列表、删除的菜品列表、删除错误信息列表、折扣、是否开放等属性。Order类还定义了一些方法,用于添加菜品、删除菜品、计算总价格等。
OrderItem类表示订单中的一项,包含索引、菜名、份量和数量四个属性。OrderItem类还定义了一个方法,用于计算该项的总价格。
Menu类表示菜单,包含一个静态Map,用于存储所有菜品。Menu类还定义了两个静态方法,用于添加菜品和获取菜品。
在主方法中,程序首先创建了一个Scanner对象来读取用户输入。然后,程序使用一个Map来存储所有订单。接下来,程序进入一个循环,每次循环读取一行输入并根据输入内容执行相应的操作。如果输入为“end”,则退出循环。如果输入以“table”开头,则创建一个新订单并将其添加到订单Map中。如果输入为两个部分且第二部分为“delete”,则从当前订单中删除指定的菜品。如果输入为两个部分,则添加一个新菜品到菜单中。如果输入为四个部分,则向当前订单中添加一项菜品。如果输入为五个部分,则向指定的订单中添加一项菜品。
在退出循环后,程序遍历所有订单并输出相关信息。
类图如下

1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner scanner = new Scanner(System.in); 6 int n = scanner.nextInt(); 7 boolean[] data = new boolean[1000001]; 8 for (int i = 0; i < n; i++) { 9 int num = scanner.nextInt(); 10 if (data[num]) { 11 System.out.println("YES"); 12 } 13 data[num] = true; 14 } 15 System.out.println("NO"); 16 } 17 }
这段代码读取用户输入的整数并检查是否有重复的整数。首先,程序创建了一个Scanner对象来读取用户输入的整数数量n。然后,程序创建了一个布尔数组data,用于存储每个整数是否出现过。接下来,程序进入一个循环,每次循环读取一个整数num。如果data[num]为true,则表示该整数已经出现过,输出“YES”。否则,将data[num]设为true。最后,程序输出“NO”。
1 import java.util.HashSet; 2 import java.util.Scanner; 3 4 public class Main { 5 public static void main(String[] args) { 6 Scanner sc = new Scanner(System.in); 7 int n = sc.nextInt(); 8 HashSet<Integer> set = new HashSet<>(); 9 StringBuilder sb = new StringBuilder(); 10 for (int i = 0; i < n; i++) { 11 int x = sc.nextInt(); 12 if (!set.contains(x)) { 13 set.add(x); 14 sb.append(x).append(" "); 15 } 16 } 17 System.out.println(sb.toString().trim()); 18 } 19 }
这段代码读取用户输入的整数并去除重复的整数。首先,程序创建了一个Scanner对象来读取用户输入的整数数量n。然后,程序创建了一个HashSet来存储不重复的整数。接下来,程序进入一个循环,每次循环读取一个整数x。如果set中不包含x,则将x添加到set中,并将x添加到StringBuilder中。最后,程序输出StringBuilder中的内容。
1 import java.util.*; 2 public class Main { 3 public static void main(String[] args) { 4 Scanner sc = new Scanner(System.in); 5 String s = sc.nextLine(); 6 s = s.replace(',', ' '); 7 s = s.replace('.', ' '); 8 String[] words = s.split(" "); 9 Arrays.sort(words, new Comparator<String>() { 10 public int compare(String a, String b) { 11 if (a.length() != b.length()) return b.length() - a.length(); 12 return a.compareToIgnoreCase(b); 13 } 14 }); 15 Set<String> set = new HashSet<>(); 16 for (String word : words) { 17 if (!set.contains(word.toLowerCase()) && word.length() > 0) { 18 System.out.println(word); 19 set.add(word.toLowerCase()); 20 } 21 } 22 } 23 }
这段代码读取用户输入的一行文本,然后按照单词长度和字母顺序对单词进行排序并去除重复的单词。首先,程序创建了一个Scanner对象来读取用户输入的一行文本。然后,程序使用replace方法将文本中的逗号和句号替换为空格。接下来,程序使用split方法将文本分割为单词数组。然后,程序使用Arrays.sort方法对单词数组进行排序。排序规则是先按照单词长度降序排列,如果长度相同,则按照字母顺序升序排列。
接下来,程序创建了一个HashSet来存储不重复的单词。然后,程序遍历单词数组。对于每个单词,如果set中不包含该单词的小写形式且该单词长度大于0,则输出该单词并将其小写形式添加到set中。
1 import java.util.Scanner; 2 public class Main{ 3 public static void main(String[] args) { 4 Scanner sc = new Scanner(System.in); 5 //调用无参构造方法,并通过setter方法进行设值 6 String sid1 = sc.next(); 7 String name1 = sc.next(); 8 int age1 = sc.nextInt(); 9 String major1 = sc.next(); 10 Student student1 = new Student(); 11 student1.setSid(sid1); 12 student1.setName(name1); 13 student1.setAge(age1); 14 student1.setMajor(major1); 15 //调用有参构造方法 16 String sid2 = sc.next(); 17 String name2 = sc.next(); 18 int age2 = sc.nextInt(); 19 String major2 = sc.next(); 20 Student student2 = new Student(sid2, name2, age2, major2); 21 //对学生student1和学生student2进行输出 22 student1.print(); 23 System.out.println(); 24 student2.print(); 25 } 26 } 27 28 class Student { 29 private String sid; 30 private String name; 31 private int age; 32 private String major; 33 34 public Student() {} 35 36 public Student(String sid, String name, int age, String major) { 37 this.sid = sid; 38 this.name = name; 39 setAge(age); 40 this.major = major; 41 } 42 43 public void print() { 44 System.out.print("学号:" + sid + ",姓名:" + name + ",年龄:" + age + ",专业:" + major); 45 } 46 47 public void setSid(String sid) { 48 this.sid = sid; 49 } 50 51 public String getSid() { 52 return sid; 53 } 54 55 public void setName(String name) { 56 this.name = name; 57 } 58 59 public String getName() { 60 return name; 61 } 62 63 public void setAge(int age) { 64 if (age > 0) { 65 this.age = age; 66 } 67 } 68 69 public int getAge() { 70 return age; 71 } 72 73 public void setMajor(String major) { 74 this.major = major; 75 } 76 77 public String getMajor() { 78 return major; 79 } 80 }
这段代码定义了一个Student类并在主方法中创建了两个Student对象。Student类包含四个私有属性:sid、name、age和major,分别表示学生的学号、姓名、年龄和专业。Student类还定义了一个无参构造方法和一个有参构造方法,用于创建Student对象。此外,Student类还定义了一些公有方法,包括get和set方法用于访问和修改属性值,以及print方法用于输出学生信息。
在主方法中,程序首先创建了一个Scanner对象来读取用户输入。然后,程序读取四个字符串并使用无参构造方法创建一个Student对象student1。接下来,程序使用set方法为student1的属性赋值。然后,程序再次读取四个字符串并使用有参构造方法创建一个Student对象student2。最后,程序调用student1和student2的print方法输出学生信息。
类图如下

1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args) { 4 Scanner scanner = new Scanner(System.in); 5 String input = scanner.nextLine(); 6 String[] parts = input.split(" "); 7 double degrees = Double.parseDouble(parts[0]); 8 double minutes = Double.parseDouble(parts[1]); 9 double seconds = Double.parseDouble(parts[2]); 10 double result = degrees + (minutes / 60) + (seconds / 3600); 11 System.out.printf("%s°%s′%s″ = %.6f", parts[0], parts[1], parts[2], result); 12 } 13 }
这段代码读取用户输入的角度、分和秒,并将其转换为十进制角度。首先,程序创建了一个Scanner对象来读取用户输入的一行文本。然后,程序使用split方法将文本分割为三个部分。接下来,程序使用Double.parseDouble方法将三个部分分别转换为角度、分和秒。然后,程序使用公式 result = degrees + (minutes / 60) + (seconds / 3600) 将角度、分和秒转换为十进制角度。最后,程序使用printf方法输出结果。
1 import java.time.LocalDate; 2 import java.time.format.DateTimeFormatter; 3 import java.time.temporal.ChronoUnit; 4 import java.util.Scanner; 5 import java.util.regex.Matcher; 6 import java.util.regex.Pattern; 7 8 public class Main { 9 public static void main(String[] args) { 10 Scanner scanner = new Scanner(System.in); 11 String firstDateString = scanner.nextLine(); 12 firstDateString = formatDate(firstDateString); 13 LocalDate firstDate = LocalDate.parse(firstDateString); 14 15 String secondDateString = scanner.nextLine(); 16 secondDateString = formatDate(secondDateString); 17 LocalDate secondDate = LocalDate.parse(secondDateString); 18 19 if (firstDate.isAfter(secondDate)) { 20 System.out.println("第一个日期比第二个日期更晚"); 21 LocalDate temp = firstDate; 22 firstDate = secondDate; 23 secondDate = temp; 24 } else if (firstDate.isBefore(secondDate)) { 25 System.out.println("第一个日期比第二个日期更早"); 26 } else { 27 System.out.println("第一个日期和第二个日期是同一天"); 28 } 29 30 long daysBetween = ChronoUnit.DAYS.between(firstDate, secondDate); 31 long weeksBetween = ChronoUnit.WEEKS.between(firstDate, secondDate); 32 System.out.println("两个日期间隔" + daysBetween + "天"); 33 System.out.println("两个日期间隔" + weeksBetween + "周"); 34 } 35 36 private static String formatDate(String dateString) { 37 Pattern pattern = Pattern.compile("(\\d{4})-(\\d{1,2})-(\\d{1,2})"); 38 Matcher matcher = pattern.matcher(dateString); 39 if (matcher.matches()) { 40 int year = Integer.parseInt(matcher.group(1)); 41 int month = Integer.parseInt(matcher.group(2)); 42 int day = Integer.parseInt(matcher.group(3)); 43 return String.format("%04d-%02d-%02d", year, month, day); 44 } else { 45 throw new IllegalArgumentException("Invalid date format: " + dateString); 46 } 47 } 48 }
这段代码读取两个日期字符串,然后将它们格式化为 yyyy-MM-dd 的格式。接着,它比较两个日期的先后顺序并输出相应的信息。最后,它计算两个日期之间相隔的天数和周数,并输出结果。
三、踩坑心得
7-1 菜单计价程序-3始终不能通过,多除显示运行超时。

四、主要困难以及改进建议
1 import java.util.*; 2 import java.text.*; 3 4 class Dish { 5 String name; 6 double price; 7 8 public Dish(String name, double price) { 9 this.name = name; 10 this.price = price; 11 } 12 } 13 14 class Order { 15 int tableNum; 16 Date time; 17 List<OrderItem> items = new ArrayList<>(); 18 List<OrderItem> deletedItems = new ArrayList<>(); 19 List<String> deleteErrors = new ArrayList<>(); 20 double discount; 21 boolean isOpen = true; 22 public Order(int tableNum, Date time) { 23 this.tableNum = tableNum; 24 this.time = time; 25 } 26 public boolean isOpen() { 27 Calendar cal = Calendar.getInstance(); 28 cal.setTime(time); 29 int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); 30 int hourOfDay = cal.get(Calendar.HOUR_OF_DAY); 31 int minuteOfHour = cal.get(Calendar.MINUTE); 32 if (dayOfWeek >= 2 && dayOfWeek <= 6) { 33 if ((hourOfDay == 10 && minuteOfHour >= 30) || (hourOfDay > 10 && hourOfDay < 14) || (hourOfDay == 14 && minuteOfHour <= 30)) { 34 discount = 0.6; 35 return true; 36 } else if ((hourOfDay == 17 && minuteOfHour >= 0) || (hourOfDay > 17 && hourOfDay < 20) || (hourOfDay == 20 && minuteOfHour <= 30)) { 37 discount = 0.8; 38 return true; 39 } else { 40 return false; 41 } 42 } else if (dayOfWeek == 1 || dayOfWeek == 7) { 43 if ((hourOfDay == 9 && minuteOfHour >= 30) || (hourOfDay > 9 && hourOfDay < 21) || (hourOfDay == 21 && minuteOfHour <= 30)) { 44 discount = 1.0; 45 return true; 46 } else { 47 return false; 48 } 49 } 50 return false; 51 } 52 public void addItem(OrderItem item) { 53 items.add(item); 54 } 55 56 public void removeItem(int index) { 57 if (index < 1 || index > items.size()) { 58 deleteErrors.add("delete error"); 59 return; 60 } 61 OrderItem item = items.get(index - 1); 62 deletedItems.add(item); 63 } 64 65 public int getTotalPrice() { 66 double totalPrice = 0.0; 67 for (OrderItem item : items) { 68 totalPrice += item.getTotalPrice(); 69 } 70 for (OrderItem item : deletedItems) { 71 totalPrice -= item.getTotalPrice(); 72 } 73 return (int) Math.round(totalPrice * discount); 74 } 75 } 76 77 class OrderItem { 78 int index; 79 String dishName; 80 int portion; 81 int quantity; 82 83 public OrderItem(int index, String dishName, int portion, int quantity) { 84 this.index = index; 85 this.dishName = dishName; 86 this.portion = portion; 87 this.quantity = quantity; 88 } 89 90 public int getTotalPrice() { 91 Dish dish = Menu.getDish(dishName); 92 if (dish == null) { 93 System.out.println(dishName + " does not exist"); 94 return 0; 95 } 96 double portionPriceFactor = 1.0; 97 if (portion == 2) { 98 portionPriceFactor = 1.5; 99 } else if (portion == 3) { 100 portionPriceFactor = 2.0; 101 } 102 return (int) Math.round(dish.price * portionPriceFactor * quantity); 103 } 104 } 105 106 class Menu { 107 static Map<String, Dish> dishes = new HashMap<>(); 108 109 public static void addDish(Dish dish) { 110 dishes.put(dish.name, dish); 111 } 112 113 public static Dish getDish(String name) { 114 return dishes.get(name); 115 } 116 } 117 118 public class Main { 119 120 public static void main(String[] args) throws ParseException { 121 122 Scanner scanner = new Scanner(System.in); 123 124 Map<Integer, Order> orders = new HashMap<>(); 125 126 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d H/m/s"); 127 128 Order currentOrder = null; 129 130 while (true) { 131 132 String line = scanner.nextLine(); 133 134 if (line.equals("end")) break; 135 136 String[] parts = line.split(" "); 137 138 if (parts[0].equals("table")) { 139 140 int tableNum = Integer.parseInt(parts[1]); 141 Date time = dateFormat.parse(parts[2] + " " + parts[3]); 142 currentOrder = new Order(tableNum, time); 143 orders.put(tableNum, currentOrder); 144 145 } else if (parts.length == 2 && parts[1].equals("delete")) { 146 147 int index = Integer.parseInt(parts[0]); 148 currentOrder.removeItem(index); 149 150 } else if (parts.length == 2) { 151 152 String dishName = parts[0]; 153 double price = Double.parseDouble(parts[1]); 154 Menu.addDish(new Dish(dishName, price)); 155 156 } else if (parts.length == 4) { 157 158 int index = Integer.parseInt(parts[0]); 159 String dishName = parts[1]; 160 int portion = Integer.parseInt(parts[2]); 161 int quantity = Integer.parseInt(parts[3]); 162 currentOrder.addItem(new OrderItem(index, dishName, portion, quantity)); 163 164 } else if (parts.length == 5) { 165 166 int tableNum = Integer.parseInt(parts[0]); 167 int index = Integer.parseInt(parts[1]); 168 String dishName = parts[2]; 169 int portion = Integer.parseInt(parts[3]); 170 int quantity = Integer.parseInt(parts[4]); 171 Order order = orders.get(tableNum); 172 if (order != null) { 173 order.addItem(new OrderItem(index, dishName, portion, quantity)); 174 } 175 176 } 177 178 } 179 int count = 0; 180 for (Order order : orders.values()) { 181 count++; 182 System.out.println("table " + order.tableNum + ": "); 183 for (OrderItem item : order.items) { 184 Dish dish = Menu.getDish(item.dishName); 185 if (dish == null) { 186 System.out.println(item.index + " " + item.dishName + " does not exist"); 187 } else { 188 System.out.println(item.index + " " + item.dishName + " " + item.getTotalPrice()); 189 } 190 } 191 for (String error : order.deleteErrors) { 192 System.out.println(error); 193 } 194 if (order.isOpen()) { 195 System.out.print("table " + order.tableNum + ": " + order.getTotalPrice()); 196 } else { 197 System.out.print("table " + order.tableNum + " out of opening hours"); 198 } 199 if (count < orders.size()) { 200 System.out.println(); 201 } 202 } 203 } 204 }
要提高运行速度,有以下几点改进建议:
- 在 Order 类中,可以使用 HashMap 来存储订单项,以便在删除订单项时能够快速定位到要删除的订单项。
- 在 Order 类中,可以使用一个变量来存储订单的总价,每次添加或删除订单项时更新该变量,以避免在计算总价时重复计算。
- 在 Menu 类中,可以使用 TreeMap 来存储菜品,以便在输出菜品信息时能够按照菜品名称的字典序输出。
1 import java.util.HashMap; 2 import java.util.Map; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 Scanner input = new Scanner(System.in); 8 Map<String, int[]> menu = new HashMap<>(); 9 menu.put("西红柿炒蛋", new int[]{15, 23, 30}); 10 menu.put("清炒土豆丝", new int[]{12, 18, 24}); 11 menu.put("麻婆豆腐", new int[]{12, 18, 24}); 12 menu.put("油淋生菜", new int[]{9, 14, 18}); 13 14 String dish; 15 int totalCost = 0; 16 while (true) { 17 dish = input.next(); 18 if (dish.equals("end")) break; 19 int size = input.nextInt(); 20 if (menu.containsKey(dish)) { 21 totalCost += menu.get(dish)[size - 1]; 22 } else { 23 System.out.println(dish + " does not exist"); 24 } 25 } 26 System.out.println(totalCost); 27 } 28 }
改进意见为:
- 可以使用
final关键字来定义常量,例如final Map<String, int[]> menu = new HashMap<>();。 - 可以使用
try-with-resources语句来自动关闭 Scanner 对象,例如try (Scanner input = new Scanner(System.in)) { ... }。 - 可以使用更具描述性的变量名,例如将
size改为portionSize。
1 import java.util.HashMap; 2 import java.util.Scanner; 3 4 public class Main { 5 public static void main(String[] args) { 6 Scanner input = new Scanner(System.in); 7 HashMap<String, Integer> menu = new HashMap<>(); 8 String A; 9 int B; 10 String C; 11 while (true) { 12 A = input.next(); 13 if (A.equals("1")) { 14 C = "1"; 15 break; 16 } 17 if (A.equals("end")) { 18 C = "0"; 19 break; 20 } 21 B = input.nextInt(); 22 menu.put(A, B); 23 } 24 int cnt = 0, sum = 0; 25 HashMap<Integer, Integer> recording = new HashMap<>(); 26 int re = 1; 27 String h = ""; 28 if (C.equals("1")) 29 while (!C.equals("end")) { 30 cnt = 0; 31 String dish = input.next(); 32 if (dish.equals("delete")) { 33 int p = Integer.parseInt(C); 34 if (!recording.containsKey(p)) System.out.println("delete error;"); 35 else { 36 sum -= recording.get(p); 37 recording.remove(p); 38 } 39 h = input.next(); 40 if (h.equals("end")) break; 41 if (!h.equals("end")) { 42 C = h; 43 continue; 44 } 45 } 46 int size1 = input.nextInt(); 47 int b = input.nextInt(); 48 49 if (!menu.containsKey(dish)) { 50 recording.put(re++, 0); 51 System.out.println(dish + " does not exist"); 52 } else { 53 int price = menu.get(dish); 54 switch (size1) { 55 case 1: 56 cnt += price; 57 break; 58 case 2: 59 cnt += Math.round(price * 1.5); 60 break; 61 case 3: 62 cnt += price * 2; 63 break; 64 } 65 cnt *= b; 66 sum += cnt; 67 recording.put(re++, cnt); 68 System.out.println(C + " " + dish + " " + cnt); 69 } 70 C = input.next(); 71 } 72 if (!C.equals("0")) 73 System.out.println(sum); 74 else System.out.println("0"); 75 } 76 }
改进意见:
- 使用更具描述性的变量名称,而不是单个字母,如
A、B和C。 - 使用
else if而不是多个if语句,使代码更具可读性。 - 在检查
A的值时,使用switch语句而不是多个if语句。 - 考虑使用不同的数据结构来存储菜单项,例如
ArrayList或数组,而不是HashMap。
1 import java.time.LocalDate; 2 import java.time.temporal.ChronoUnit; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 Scanner scanner = new Scanner(System.in); 8 String firstDate = scanner.nextLine(); 9 String[] secondDates = scanner.nextLine().split(" "); 10 scanner.close(); 11 12 // Check if the first date is valid 13 if (isValidDate(firstDate)) { 14 LocalDate date = LocalDate.parse(firstDate); 15 if (isLeapYear(date.getYear())) { 16 System.out.println(firstDate + "是闰年."); 17 } 18 System.out.println(firstDate + "是当年第" + date.getDayOfYear() + "天,当月第" + date.getDayOfMonth() + "天,当周第" + date.getDayOfWeek().getValue() + "天."); 19 20 } else { 21 System.out.println(firstDate + "无效!"); 22 } 23 24 // Check if the second dates are valid 25 if (isValidDate(secondDates[0]) && isValidDate(secondDates[1])) { 26 LocalDate startDate = LocalDate.parse(secondDates[0]); 27 LocalDate endDate = LocalDate.parse(secondDates[1]); 28 29 if (endDate.isBefore(startDate)) { 30 System.out.print(endDate.toString() +"早于"+ startDate.toString() +",不合法!"); 31 return; 32 } 33 34 long daysBetween = ChronoUnit.DAYS.between(startDate, endDate); 35 long monthsBetween = endDate.getMonthValue()-startDate.getMonthValue(); 36 long yearsBetween = Math.abs(endDate.getYear()-startDate.getYear()); 37 38 System.out.print(endDate.toString()+ "与" + startDate.toString() + 39 "之间相差" + daysBetween + 40 "天,所在月份相差" + monthsBetween + 41 ",所在年份相差" + yearsBetween + 42 "."); 43 } else { 44 System.out.print(secondDates[0] +"或"+ secondDates[1] +"中有不合法的日期."); 45 } 46 } 47 48 private static boolean isValidDate(String dateString) { 49 try { 50 LocalDate.parse(dateString); 51 return true; 52 } catch (Exception e) { 53 return false; 54 } 55 } 56 57 private static boolean isLeapYear(int year) { 58 return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 59 } 60 }
改进意见:
- 在
isValidDate方法中,可以使用DateTimeFormatter类来指定日期格式,以便更好地检查日期是否有效。 - 在计算两个日期之间相差的月数和年数时,可以使用
ChronoUnit.MONTHS.between和ChronoUnit.YEARS.between方法,而不是直接计算两个日期的月份和年份之差。 - 可以考虑将输入和输出部分的代码封装到单独的方法中,以便更好地组织代码。
- 可以考虑使用异常处理来处理无效的输入,而不是直接在控制台输出错误信息。
1 import java.util.Scanner; 2 public class Main{ 3 public static void main(String[] args) { 4 Scanner sc = new Scanner(System.in); 5 //调用无参构造方法,并通过setter方法进行设值 6 String sid1 = sc.next(); 7 String name1 = sc.next(); 8 int age1 = sc.nextInt(); 9 String major1 = sc.next(); 10 Student student1 = new Student(); 11 student1.setSid(sid1); 12 student1.setName(name1); 13 student1.setAge(age1); 14 student1.setMajor(major1); 15 //调用有参构造方法 16 String sid2 = sc.next(); 17 String name2 = sc.next(); 18 int age2 = sc.nextInt(); 19 String major2 = sc.next(); 20 Student student2 = new Student(sid2, name2, age2, major2); 21 //对学生student1和学生student2进行输出 22 student1.print(); 23 System.out.println(); 24 student2.print(); 25 } 26 } 27 28 class Student { 29 private String sid; 30 private String name; 31 private int age; 32 private String major; 33 34 public Student() {} 35 36 public Student(String sid, String name, int age, String major) { 37 this.sid = sid; 38 this.name = name; 39 setAge(age); 40 this.major = major; 41 } 42 43 public void print() { 44 System.out.print("学号:" + sid + ",姓名:" + name + ",年龄:" + age + ",专业:" + major); 45 } 46 47 public void setSid(String sid) { 48 this.sid = sid; 49 } 50 51 public String getSid() { 52 return sid; 53 } 54 55 public void setName(String name) { 56 this.name = name; 57 } 58 59 public String getName() { 60 return name; 61 } 62 63 public void setAge(int age) { 64 if (age > 0) { 65 this.age = age; 66 } 67 } 68 69 public int getAge() { 70 return age; 71 } 72 73 public void setMajor(String major) { 74 this.major = major; 75 } 76 77 public String getMajor() { 78 return major; 79 } 80 }
- 在
Student类中添加一个toString方法,用于返回学生信息的字符串表示。这样,在main方法中就可以直接使用System.out.println(student1)来输出学生信息,而不需要调用print方法。 - 在
setAge方法中,可以添加一些对年龄的合法性检查,例如检查年龄是否在一个合理的范围内。如果年龄不合法,可以抛出一个异常,而不是什么都不做。 - 可以考虑在
Student类中添加一些其他方法,例如计算学生的平均成绩、判断学生是否及格等。 - 可以考虑使用枚举类型来表示学生的专业,而不是使用字符串。
五、总结
通过这些题目,我学习了如何使用HashMap来存储和检索数据,以及如何使用循环和条件语句来处理用户输入。
它们涵盖了许多不同的主题和概念。例如,有些题目演示了如何使用集合(如HashMap和HashSet)来存储和检索数据,有些题目演示了如何使用循环和条件语句来处理用户输入,还有些题目演示了如何使用正则表达式来匹配和提取字符串中的信息。
通过这些题目,我们可以学习到许多有用的Java编程技能和概念。不过,这些程序的代码结构和可读性还有待改进。例如,可以使用更清晰的变量名和方法名,以及更好地组织代码来提高可读性。此外,这些程序对无效输入的处理也不够完善,可以进一步学习如何处理无效输入。
总之,这些题目为我们提供了一个很好的学习机会,可以帮助我们更好地掌握Java编程技能。但是,我们仍然需要继续学习和研究,以便更好地理解这些概念并将它们应用到实际编程中。