PAT乙级21到40题练习代码全纪录

  • 废话完了开正题(21到40题,没标注就是测试点全通过)
    • 1021 个位数统计
    • 1022 D进制的A+B
    • 1023 组个最小数
    • 1024 科学计数法
    • 1025 反转链表(测试点5运行超时)
    • 1026 程序运行时间
    • 1027 打印沙漏
    • 1028 人口普查(测试点4运行超时)
    • 1029 旧键盘
    • 1030 完美数列(测试点4运行超时)
    • 1031 查验身份证
    • 1032 挖掘机技术哪家强(测试点3运行超时)
    • 1033 旧键盘打字
    • 1034 有理数四则运算
    • 1035 插入与归并
    • 1036 跟奥巴马一起编程
    • 1037 在霍格沃兹找零钱
    • 1038 统计同成绩学生(测试点3运行超时)
    • 1039 到底买不买
    • 1040 有几个PAT

其实PAT的坑在刷题过程中就会发现,还是有迹可循的。常见的坑点如:输入样例的 数据类型范围限制特殊输入的情况,比如0;输出数据的 格式;“不超过”,“不低于”等字样表示的 边界值情况等。最难识别的还是题目的 逻辑盲点,总之题要好好分析再想解决问题的思路,先理解好题目才能不走弯路!

废话完了开正题(21到40题,没标注就是测试点全通过)

1021 个位数统计

import java.util.Scanner;
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String num = sc.nextLine();int[] count = new int[10];for(int i = 0; i < num.length(); i++) {switch(num.charAt(i)) {case '0':  count[0]++;   continue;case '1':    count[1]++;   continue;case '2':    count[2]++;   continue;case '3':    count[3]++;   continue;case '4':    count[4]++;   continue;case '5':    count[5]++;   continue;case '6':    count[6]++;   continue;case '7':    count[7]++;   continue;case '8':    count[8]++;   continue;case '9':    count[9]++;   continue;}}for(int i = 0; i < 10; i++) {if(count[i]!=0) {System.out.println(i+":"+count[i]);}}}
}

1022 D进制的A+B

注意结果为0的情况哦!

import java.util.Scanner;
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int A = sc.nextInt();int B = sc.nextInt();int D = sc.nextInt();int dec = A + B;StringBuilder numD = new StringBuilder("");if(dec == 0){numD.append("0");}else{while(dec > 0) {numD.append(dec % D);dec = dec / D;}}System.out.println(numD.reverse().toString());}
}

1023 组个最小数

唯一要注意的就是寻找开头数字的条件:数字不为0,计数不为0,并且是计数不为0的数字中最小的数字。剩下的按照有小到大排列即可。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] temp = br.readLine().trim().split("\\s+");int[] count = new int[10];int firstDigit = 0;boolean minNotZero = true;for (int i = 0; i < 10; i++) {count[i] = Integer.valueOf(temp[i]);if (i != 0 && minNotZero == true && count[i] != 0) { // 找到非0的最小数字并将对应的计数减1firstDigit = i;count[i]--;minNotZero = false;}}StringBuilder str = new StringBuilder(String.valueOf(firstDigit));for (int i = 0; i < 10; i++) {for (int j = 0; j < count[i]; j++)str.append(String.valueOf(i));}System.out.println(str);}
}

1024 科学计数法

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] input = br.readLine().trim().split("E|\\.");char sign1 = input[0].charAt(0);   // sign1是整数部分的正负号char sign2 = input[2].charAt(0);  // sign2是指数部分的正负号StringBuilder result = new StringBuilder(input[0].charAt(1)+input[1]);   // result最终得到输出结果,首先加入小数点左侧的一位数字[1-9],再加入小数点右侧的数字串String[] temp = input[2].split("\\+|\\-"); int exp = Integer.parseInt(temp[1]); // exp存储指数部分的数字if (sign2 == '-') {for (int i = 0; i < exp; i++)result.insert(0, '0');result.insert(1, '.');} else {int pointMove = exp - input[1].length();if (pointMove >= 0) {    // pointMove大于等于0则小数部分为0,即结果为整数,增加0即可for (int i = 0; i < pointMove; i++)result.append('0');}else {                    // pointMove小于0则挪动小数点,并插入小数点,即结果为浮点数result.insert((exp + 1), '.');}}if (sign1 == '-')result.insert(0, '-');System.out.println(result);}
}

1025 反转链表(测试点5运行超时)

本题最大坑点在有可能无法完全遍历链表,如果出现了-1就要提前结束,用-1之前的进行反转排序并输出。另外输出格式要格外注意。测试点5用Java过不了。

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.BufferedReader;
public class Main {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] str = br.readLine().trim().split("\\s+");int firstNode = Integer.valueOf(str[0]);int n = Integer.parseInt(str[1]);int k = Integer.parseInt(str[2]);Node[] nodes = new Node[100000];while (n-- > 0) {String[] temp = br.readLine().trim().split("\\s+");nodes[Integer.valueOf(temp[0])] = new Node(temp[0], Integer.valueOf(temp[1]), Integer.valueOf(temp[2]));}int address = firstNode;ArrayList<Integer> record = new ArrayList<>();while (address != -1) {                         // -1之前的记录下来record.add(address);address = nodes[address].nextNode;}int count = 0;while (record.size() >= (count + 1) * k)        // 每k个反转一次,分别为0到k-1,k到2k-1……reverse(record, count++ * k, count * k - 1);for (int i = 0; i < record.size()-1; i++)System.out.println(nodes[record.get(i)].address+" "+nodes[record.get(i)].value + " "+nodes[record.get(i+1)].address);System.out.println(nodes[record.get(record.size()-1)].address+" "+nodes[record.get(record.size()-1)].value + " -1");}public static void reverse(ArrayList<Integer> record, int start, int end) {while (start < end) {int temp = record.get(start);                // swaprecord.set(start++, record.get(end));record.set(end--, temp);}}
}class Node {String address;                                    // 便于输出int value;int nextNode;public Node() {}public Node(String address, int value, int nextNode) {this.address = address;this.value = value;this.nextNode = nextNode;}
}

1026 程序运行时间

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {// 输入在一行中顺序给出 2 个整数 C1 和 C2。注意两次获得的时钟打点数肯定不相同,即 C1 < C2BufferedReader br = new BufferedReader(new InputStreamReader(System.in));final int CLK_TCK = 100;String[] str = br.readLine().trim().split("\\s+");double C1 = Double.parseDouble(str[0]);double C2 = Double.parseDouble(str[1]);int gap = (int) Math.round((C2 - C1) / CLK_TCK);int[] time = new int[3];time[2] = gap % 60; // 秒time[1] = ((gap - time[0]) / 60) % 60; // 分time[0] = ((gap - time[0]) / 60 - time[1]) / 60; // 时for(int i = 0; i < 3; i++) {if(time[i] < 10)System.out.print("0"); // 不够两位就要用0补位System.out.print(time[i]);if(i < 2)System.out.print(":");}}
}

1027 打印沙漏

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] str = br.readLine().trim().split("\\s+");int n = Integer.parseInt(str[0]);char c = str[1].charAt(0);int count = 1, index = 1;while (count <= n) {count += 2 * (2 * index + 1);index++;}if (n != 0)count -= 2 * (2 * (index - 1) + 1); // 会多算一次elsecount = 0;int row = (index - 2) * 2; // row指沙漏打印0到row行/* 打印上半部分,直到一行内的符号为1个,共打印 row/2+1行 */for (int i = 0; i <= row / 2; i++) { for (int j = 0; j < i; j++) // 思路:第一行0个并且递增System.out.print(" ");for (int k = 1; k <= 2 * (row / 2 - i) + 1; k++) // 思路:第row/2行打印1个System.out.print(c);System.out.println();}/* 打印下半部分,共打印 row/2行,打印行数为row/2+1到row行 */for (int i = row / 2 + 1; i <= row; i++) { for (int j = 0; j < row - i; j++) // 思路:第row行打印0个并递减System.out.print(" ");for (int k = 1; k <= 2 * (i - row / 2) + 1; k++) // 思路:第row/2+1行打印3个System.out.print(c);System.out.println();}System.out.println(n - count);}
}

1028 人口普查(测试点4运行超时)

坑!一道只要用java,就基本无法避免第4个测试点超时运行的题。之前题目无论怎样,只要改变写法总还是能找到可以全通过的方法,这一道真的艰难。但是以下还是提供些能通过0-3测试点的写法(们)。
注意:要通过第三个测试点必须注意输入0时,输出为0。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int N = Integer.parseInt(br.readLine());ArrayList<Citizen> list = new ArrayList<>();for (int i = 0; i < N; i++) {String[] in = br.readLine().trim().split("\\s|/");Citizen c = new Citizen(in[0], in[1], in[2], in[3]);if (c.isLegel()) // 符合输入要求才加入数组列表list.add(c);}int old = 0, young = 0; // 用来记录最老和最年轻的序号if (list.size() > 0) {Calendar oldest = list.get(0).birthday;Calendar youngest = list.get(0).birthday;for (int i = 0; i < list.size(); i++) {if (list.get(i).birthday.before(oldest)) { // 找出最老oldest = list.get(i).birthday;old = i;}if (list.get(i).birthday.after(youngest)) { // 找出最年轻youngest = list.get(i).birthday;young = i;}}System.out.println(list.size() + " " + list.get(old).name + " " + list.get(young).name);}elseSystem.out.println("0");}
}class Citizen { // 用Comparable大概会更慢吧……我就不尝试了String name;Calendar birthday = Calendar.getInstance();public Citizen() {}public Citizen(String str, String y, String m, String d) {name = str;birthday.set(Integer.parseInt(y), Integer.parseInt(m) - 1, Integer.parseInt(d));// 这里要注意Calendar的set方法中月份从0开始,因而输入时要比实际月份-1}public boolean isLegel() {boolean flag = false;Calendar now = Calendar.getInstance();now.clear();now.set(2014, 8, 7);Calendar earliest = Calendar.getInstance();earliest.clear();earliest.set(1814, 8, 6);if (birthday.after(earliest) && birthday.before(now))flag = true;return flag;}
}


一次不行再试一次,于是努力地往便捷地写,把日期比较简化成比较数字大小。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int N = Integer.valueOf(br.readLine());String theElder = null, theYoung = null ; // 记录最长者和最年轻者的名字int oldest = 0, youngest = 0; // 记录最长者和最年轻者的生日int count = 0; // 记录符合要求的个数for (int i = 0; i < N; i++) {String[] temp = br.readLine().trim().split("\\s|/");int bday = Integer.valueOf(temp[1] + temp[2] + temp[3]);if (bday >= 18140906 && bday <= 20140906) {count++;if (count == 1) {oldest = bday;youngest = bday;theElder = temp[0];theYoung = temp[0];} else {if (bday < oldest) {oldest = bday;theElder = temp[0];}if (bday > youngest) {youngest = bday;theYoung = temp[0];}}}}if (count > 0)System.out.println(count + " " + theElder + " " + theYoung);elseSystem.out.println("0");}
}


这个地步还不行我就放弃了……一搜发现根本找不到能全通过的java写法,C++也不能用String而是strcmp方法(总之费劲啊),附上其他语言的满分解答。
C C++ Python

1029 旧键盘

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String input = br.readLine().toUpperCase(); // 键盘输入String str1 = br.readLine().toUpperCase(); // 实际输入ArrayList<Character> output = new ArrayList<>(); // 将实际输入转化成数组列表以使用contains方法char[] temp = str1.toCharArray();for (int i = 0; i < str1.length(); i++)output.add(temp[i]);ArrayList<Character> brokenKey = new ArrayList<>(); // 坏键for (int i = 0; i < input.length(); i++) {Character ch = input.charAt(i);if (output.contains(ch) == false && brokenKey.contains(ch) == false) // 未能实际输入并且还尚未记录brokenKey.add(ch);}for(int i = 0; i < brokenKey.size(); i++)System.out.print(brokenKey.get(i));}
}

1030 完美数列(测试点4运行超时)

最后一个测试点考察的依旧是数据类型,输入数据均小于109,但是在乘法过程中就可能出现1018,但是int型取值为-231~231-1,大概是十位,也就是说用int可能溢出。倒数第二个测试点java写运行超时难以避免。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
public class Main {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] str1 = br.readLine().trim().split("\\s+");int N = Integer.parseInt(str1[0]);int p = Integer.parseInt(str1[1]);String[] str2 = br.readLine().trim().split("\\s+");ArrayList<Long> perfect = new ArrayList<>(); // 避免溢出用Long类for (int i = 0; i < N; i++) {perfect.add(Long.parseLong(str2[i]));}Collections.sort(perfect); // 升序排序int start = 0, count = 0;int optimal = 0; // 存储最佳结果while (true) {count = 0;for(int i = start; i < N; i++) {if(perfect.get(i) <= perfect.get(start) * p)count++;elsebreak;}if (count > optimal)optimal = count;start++;if (optimal >= N - start) // 如果剩余长度不大于最佳结果,则当前结果必为最佳break;}System.out.println(optimal);}
}

附上C++满分答案:C++

1031 查验身份证

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int N = Integer.valueOf(br.readLine()); // N个待查验的身份证号ArrayList<String> list = new ArrayList<>(); // 错误的身份证号for (int i = 0; i < N; i++) {String in = br.readLine().trim();if (isLegel(in) != in.charAt(17)) // 检查最后一个校验码是否正确list.add(in);}if(list.size()==0)System.out.println("All passed");else {for(int i = 0; i < list.size(); i++)System.out.println(list.get(i));}}private static char isLegel(String in) {int total = (in.charAt(0)-'0')*7;total += (in.charAt(1)-'0')*9;total += (in.charAt(2)-'0')*10;total += (in.charAt(3)-'0')*5;total += (in.charAt(4)-'0')*8;total += (in.charAt(5)-'0')*4;total += (in.charAt(6)-'0')*2;total += (in.charAt(7)-'0')*1;total += (in.charAt(8)-'0')*6;total += (in.charAt(9)-'0')*3;total += (in.charAt(10)-'0')*7;total += (in.charAt(11)-'0')*9;total += (in.charAt(12)-'0')*10;total += (in.charAt(13)-'0')*5;total += (in.charAt(14)-'0')*8;total += (in.charAt(15)-'0')*4;total += (in.charAt(16)-'0')*2;char M = 0;switch(total%11) {case 0: M = '1'; break;case 1: M = '0'; break;case 2: M = 'X'; break;case 3: M = '9'; break;case 4: M = '8'; break;case 5: M = '7'; break;case 6: M = '6'; break;case 7: M = '5'; break;case 8: M = '4'; break;case 9: M = '3'; break;case 10: M = '2';}return M;}}

1032 挖掘机技术哪家强(测试点3运行超时)

坑!(又)一道只要用java,就基本无法避免第3个测试点超时运行的题,以下提供些能通过0到2测试点的方式。思路很明显,有key有value用HashMap<>。

import java.util.HashMap;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int N = Integer.parseInt(br.readLine().trim());HashMap<Integer, Integer> teamMap = new HashMap<>();int teamID = 0, points = 0; // 输入的队伍,分数Integer max = 0, index = 0; // 当前最高分,最高分所在队伍for(int i = 0; i < N; i++) {String[] str = br.readLine().trim().split("\\s+");teamID = Integer.parseInt(str[0]);points = Integer.parseInt(str[1]);if(teamMap.containsKey(teamID)) { // 输入的该队伍是否记录过teamMap.put(teamID, teamMap.get(teamID) + points);}else {teamMap.put(teamID, points);}if(teamMap.get(teamID)>max) { // 找最高分max = teamMap.get(teamID);index = teamID;}}System.out.println(index+" "+max);  }
}


累……累了,附上满分其他语言答案:C/C++

1033 旧键盘打字

弄清楚坏键对需要打印的字符串的影响:

  1. 如果 ‘+’(此处指大写锁定键)坏了,大写字母无法打印;
  2. 坏键中字母以大写表示,则字符串中此字母无论大小写都无法打印;
  3. 其他坏键只要在字符串中出现就无法打印。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String str0 = br.readLine().trim();String input = br.readLine().trim();ArrayList<Character> brokenKey = new ArrayList<>(); // 将第一行输入的坏键转换成数字列表,以便使用contains方法for (int i = 0; i < str0.length(); i++)brokenKey.add(str0.charAt(i));StringBuilder output = new StringBuilder(""); // 初始化为空字符串for (int i = 0; i < input.length(); i++) {Character ch = input.charAt(i);if (brokenKey.contains('+') && Character.isUpperCase(ch)) // 如果大写锁定键坏了而且当前需要打印的字母为大写,跳过continue;Character ch2 = Character.isLetter(ch) ? Character.toUpperCase(ch) : ch;if (brokenKey.contains(ch2)) // 如果坏键和当前需要打印的一致,跳过continue;output.append(ch);}System.out.println(output.toString());}
}

1034 有理数四则运算

哈……数据类型是永远的坑。如果是后两个测试点不通过而前两个通过了,问题一般就是出在了int型上。因为在计算过程中(尤其是乘法)比较容易超出int范围。我想到的解决方法有二:

  1. 改用long,gcd自己写,可以用辗转相除法化简
  2. 改用BigInteger类,调用gcd方法化简

另外,在转换成标准格式的分数过程中,还需要注意:

  1. 虽然题目有说仅在分子前有负号,但计算中也可能出现分子分母都为负的情况(除法)
  2. 若除法分母为 0,输出Inf
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] str = br.readLine().trim().split("\\s+|/");BigInteger a1 = new BigInteger(str[0]);BigInteger b1 = new BigInteger(str[1]);BigInteger a2 = new BigInteger(str[2]);BigInteger b2 = new BigInteger(str[3]);String str0 = simplify(a1, b1);String str1 = simplify(a2, b2);System.out.println(str0 + " + " + str1 + " = " + simplify(a1.multiply(b2).add(a2.multiply(b1)), b1.multiply(b2)));System.out.println(str0 + " - " + str1 + " = " + simplify(a1.multiply(b2).add(a2.multiply(b1).negate()), b1.multiply(b2)));System.out.println(str0 + " * " + str1 + " = " + simplify(a1.multiply(a2), b1.multiply(b2)));System.out.print(str0 + " / " + str1 + " = ");if (str1 == "0")System.out.println("Inf");elseSystem.out.println(simplify(a1.multiply(b2), b1.multiply(a2)));}private static BigInteger[] divideGCD(BigInteger a, BigInteger b) {BigInteger gcd = a.gcd(b);a = a.divide(gcd);b = b.divide(gcd);BigInteger[] result = {a,b};return result;}private static String simplify(BigInteger a, BigInteger b) {StringBuilder simp = new StringBuilder("");if (a.equals(BigInteger.ZERO)) // 分子为0直接返回0return "0";boolean isOdd = a.multiply(b).compareTo(BigInteger.ZERO) < 0 ? true : false;if (isOdd)simp.append("(-");a = a.abs(); // 将两个数字取绝对值b = b.abs();while(a.gcd(b).compareTo(BigInteger.ONE)>0) { // 将两个数字除以所有非1公约数BigInteger[] temp = divideGCD(a,b);a = temp[0];b = temp[1];}BigInteger[] part = a.divideAndRemainder(b);if (part[0].compareTo(BigInteger.ONE)>=0) { // 取整数部分simp.append(part[0]);a = part[1];if (a.compareTo(BigInteger.ZERO)>0)simp.append(" ");}if (a.compareTo(BigInteger.ZERO)>0) // 取分数部分simp.append(a + "/" + b);if (isOdd)simp.append(")");return simp.toString();}
}

1035 插入与归并

我看到许多人都是直接用sort写的,这里就当作是训练自己的基础算法了,自己写了完整的非递归归并排序和仅一步的插入排序。思路如下:

  1. 先判定插入还是归并,根据题目要求,只可能为二者之一,于是发现插入排序的判断条件为:从结束升序的数字开始,接下来的数列中数字均与原数列中对应位置数字相同

10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
1 2 3 5 7 8 9 4 6 0 // 样例输出结果

  1. 判断为插入排序:以当前数组match为对象,从标记结束升序的位置,将此位置对应数字向前插入至其正确顺序的位置
  2. 判断为归并排序:以原始数组ori为对象,从步长为2开始,逐次将步长*2。将步长内子数组分为左右两组,按照大小进行归并,并将超出原始数组的部分略去

另外,过程中通过测试可以发现,测试点0、2、4是插入排序; 测试点1、3、5、6是归并排序,并且5、6与 (n % len != 0)的情况有关,并且测试点5的步长至少大于8

import java.io.InputStreamReader;
import java.util.Arrays;
import java.io.BufferedReader;
public class Main {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine().trim());String[] str1 = br.readLine().trim().split("\\s+");String[] str2 = br.readLine().trim().split("\\s+");int[] ori = new int[n];        // 原始数组int[] match = new int[n];       // 将要进行比对的数组int pos = 0;                   // 结束升序的位置,0表示还没找到boolean isInsertion = true;for (int i = 0; i < n; i++) {ori[i] = Integer.parseInt(str1[i]);match[i] = Integer.parseInt(str2[i]);if (pos == 0 && i > 0 && match[i] < match[i - 1]) // 标记升序结束pos = i;if (pos != 0 && ori[i] != match[i]) // 结束升序后,比对数组是否与原数组相同,不同则不是插入排序isInsertion = false;}if (isInsertion) {System.out.println("Insertion Sort");ori = match;insertionSort(ori, 0, pos);} else {System.out.println("Merge Sort");int len = 1;boolean eureka = false;while (eureka == false) {eureka = Arrays.equals(ori, match); // 变化后数组与比对数组相同则本轮结束后退出循环len *= 2;for (int i = 0; i < n; i += len) {  // 共i个步长的子数组mergeSort(ori, i, len);}}}for (int i = 0; i < n - 1; i++)                // 打印最终结果System.out.print(ori[i] + " ");System.out.println(ori[n - 1]);}private static void mergeSort(int[] arr, int from, int len) {int to = Math.min(from + len - 1, arr.length - 1); // 结束排序的位置,即右侧的终点int mid = from + len / 2;  // 一分为二,为右侧的开端int current1 = from;int current2 = mid;int current3 = 0; // 临时数组的序号int[] temp = new int[len];while (current1 <= mid - 1 && current2 <= to) {if (arr[current1] < arr[current2]) {temp[current3++] = arr[current1++];} else {temp[current3++] = arr[current2++];}}while (current1 <= mid - 1 && current1 < arr.length) // 要小心这里也可能溢出temp[current3++] = arr[current1++];while (current2 <= to)temp[current3++] = arr[current2++];int k = 0;while (from < arr.length && k < temp.length)arr[from++] = temp[k++];}private static void insertionSort(int[] arr, int start, int pos) {for (int i = pos - 1; i >= start; i--) {if (arr[pos] < arr[i]) {int temp = arr[pos];arr[pos] = arr[i];arr[i] = temp;pos = i;}}}
}

1036 跟奥巴马一起编程

import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] str1 = br.readLine().trim().split("\\s+");int n = Integer.parseInt(str1[0]); // 边长char ch = str1[1].charAt(0);int wid = (int) Math.round((double) n / 2);  // 注意四舍五入for (int j = 0; j < wid; j++) {if (j == 0 || j == wid - 1) {for (int i = 0; i < n; i++)System.out.print(ch);System.out.println();} else {System.out.print(ch);for (int i = 0; i < n - 2; i++)System.out.print(" ");System.out.println(ch);}}}}

1037 在霍格沃兹找零钱

import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] str1 = br.readLine().trim().split("\\.|\\s");long[] gallon = new long[3];long[] sickle = new long[3];long[] knut = new long[3];long[] total = new long[2];     // 算总价,以knut为单位int j = 0;for (int index = 0; index < 2; index++) {gallon[index] = Long.parseLong(str1[j++]);sickle[index] = Long.parseLong(str1[j++]);knut[index] = Long.parseLong(str1[j++]);total[index] = gallon[index]*17*29 + sickle[index]*29 + knut[index];}long change = total[1] - total[0]; // 算差价,以knut为单位if(change < 0) {System.out.print("-");change = Math.abs(change);}knut[2] = change % 29;sickle[2] = ((change - knut[2]) / 29) % 17;gallon[2] = (change - knut[2] - sickle[2] * 29)/(17*29);System.out.println(gallon[2]+"."+sickle[2]+"."+knut[2]);}
}

1038 统计同成绩学生(测试点3运行超时)

可以用hashmap,很慢就对了

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;public class Main {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine().trim());String[] str1 = br.readLine().trim().split("\\s+");String[] str2 = br.readLine().trim().split("\\s+");int num = Integer.parseInt(str2[0]); // 待计数的分数个数HashMap<Integer, Integer> gradeMap = new HashMap<>();for (int i = 1; i <= num; i++) {gradeMap.put(Integer.parseInt(str2[i]), 0);}int grade = 0;for (int i = 0; i < n; i++) {grade = Integer.parseInt(str1[i]);gradeMap.computeIfPresent(grade, (k, v) -> v + 1); // key值出现就value+1}for(int i = 1; i <= num; i++) {System.out.print(gradeMap.get(Integer.parseInt(str2[i])));if(i != num)System.out.print(" ");}}
}

纯粹用数组快了不少,但最后一个测试点还是过不了

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;public class Main {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine().trim());String[] str1 = br.readLine().trim().split("\\s+");String[] str2 = br.readLine().trim().split("\\s+");int k = Integer.parseInt(str2[0]); // 待计数的分数个数int[] match = new int[k];for (int i = 1; i <= k; i++) {match[i - 1] = Integer.parseInt(str2[i]);}int[] count = new int[k];int grade = 0;for (int i = 0; i < n; i++) {grade = Integer.parseInt(str1[i]);for (int j = 0; j < k; j++) {if (grade == match[j]) {count[j]++;break;}}}for(int i = 0; i < k-1; i++)System.out.print(count[i]+" ");System.out.println(count[k-1]);}
}

1039 到底买不买

hashmap只能通过最后一个测试点,太慢了

import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.io.BufferedReader;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String a = br.readLine().trim();String b = br.readLine().trim();HashMap<Character, Integer> beads = new HashMap<>(); // 建立珠子和个数间的映射Character ch;for (int i = 0; i < b.length(); i++) {ch = b.charAt(i);if (beads.containsKey(ch)) {beads.compute(ch, (k, v) -> v + 1); // 找到已存在的,就将映射个数+1} else {beads.put(ch, 1); // 找到第一次出现的就初始化}}for (int i = 0; i < a.length(); i++) {ch = a.charAt(i);if (beads.containsKey(ch)) {if (beads.get(ch) > 0) {beads.compute(ch, (k, v) -> v - 1); // 找到一个对应的珠子,个数-1}}}Iterator<Character> it = beads.keySet().iterator();int count = 0; // 统计剩余珠子个数while (it.hasNext()) {ch = it.next();count += beads.get(ch);}/* 打印结果 */if (count == 0)System.out.println("Yes " + (a.length() - b.length()));elseSystem.out.println("No " + count);}
}

于是又想到了数组列表,终于全部通过了。

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String a = br.readLine().trim();String str = br.readLine().trim();ArrayList<Character> b = new ArrayList<>();for (int i = 0; i < str.length(); i++) {b.add(str.charAt(i));}/* 在a串中找到一个珠子,就将b串中的最后一个对应珠子移除 */Character ch;int pos;for (int i = 0; i < a.length(); i++) {ch = a.charAt(i);if (b.contains(ch)) {pos = b.lastIndexOf(ch);b.remove(pos);}if (b.size() == 0) // 如果已经全部找到了就停止break;}/* 打印结果 */int size = b.size();if (size == 0)System.out.println("Yes " + (a.length() - str.length()));elseSystem.out.println("No " + size);}
}

1040 有几个PAT

本题需要花费一定时间理解题意所示的计算方式,比较好的方式是自己先写出来一个比较复杂的字串,如:ATAPPTATPATTAPT。分析思路如下:

  1. 我们不难发现,第一个P之前出现的字母是没有意义的,因此排除在外,将PPTATPATTAPT作为有效字串;
  2. P后出现的第一个A前,如果有其他字母无须计算在内,即PTAT仅包含1个PAT;
  3. 一个A后有多少个T,即可以此A组成多少个AT;
  4. 一个P后有多少个AT,就相当于每个A组成AT数之和;
  5. 为便于计算,由后向前看。
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String str = br.readLine().trim(); // 长度不超过100000,即在整型范围内int firstP = str.indexOf('P');String a = str.substring(firstP); // a为有效部分int countA = 0;int countT = 0;long count = 0;int lastT = a.lastIndexOf('T');for (int i = lastT; i >= 0; i--) {if (a.charAt(i) == 'P')count += countA;            // 当前P后有多少个ATif (a.charAt(i) == 'A')countA += countT;           // 当前A后有多少个T,就可以组成多少个ATif (a.charAt(i) == 'T')countT++;}count = count % 1000000007; System.out.println(count);}
}

【Java】PAT乙级真题全记录(二)21到40题相关推荐

  1. 【PTA】 PAT乙级真题,95题(C++,AC代码)

    PAT乙级真题95题 标号 标题 分数 通过数 提交数 通过率 1001 害死人不偿命的(3n+1)猜想 15 109558 309119 0.35 1002 写出这个数 20 71739 28156 ...

  2. PAT乙级真题1058 || 选择题(详解,C/C++示例,测试点分析)

    [欢迎关注微信公众号:计算机黑科学大全,对话框回复:PAT乙级真题]获取全部真题详解及代码示例 个人博客地址:https://mzwang.top 选择题 题目描述: 批改多选题是比较麻烦的事情,本题 ...

  3. 1085 PAT单位排行 (25分)-PAT乙级真题-C++实现

    1085 PAT单位排行 (25分)-PAT乙级真题-C++实现 题目描述: 每次 PAT 考试结束后,考试中心都会发布一个考生单位排行榜.本题就请你实现这个功能. 输入格式: 输入第一行给出一个正整 ...

  4. PAT乙级真题1089 || 狼人杀-简单版(详解,C/C++示例,测试点分析)

    [欢迎关注微信公众号:计算机黑科学大全,在对话框回复:PAT乙级真题]获取全部真题详解及代码示例,邀请大家加入PAT算法刷题交流qq群:821388108 个人博客:https://mzwang.to ...

  5. 【Java】PAT乙级真题全记录(三)41到60题

    PAT乙级41到60题练习代码全纪录 1041 考试座位号 1042 字符统计 1043 输出PATest 1044 火星数字 1045 快速排序(1.3.4.5测试点运行超时) 1046 划拳 10 ...

  6. 「PAT乙级真题解析」Basic Level 1004 (问题分析+完整步骤+伪代码描述+提交通过代码)

    乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范.从小白开始逐步掌握用编程解决问题. PAT乙级BasicLevelPractice 1004 需求分析 思路一: 以终为始分解需 ...

  7. 1051. 复数乘法 (15)-PAT乙级真题

    复数可以写成(A + Bi)的常规形式,其中A是实部,B是虚部,i是虚数单位,满足i2 = -1:也可以写成极坐标下的指数形式(R*e(Pi)),其中R是复数模,P是辐角,i是虚数单位,其等价于三角形 ...

  8. 「PAT乙级真题解析」Basic Level 1033 旧键盘打字 (问题分析+完整步骤+伪代码描述+提交通过代码)

    乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范.从小白开始逐步掌握用编程解决问题. PAT乙级BasicLevelPractice 1033 问题分析 题目设定了一个场景: 有 ...

  9. 「PAT乙级真题解析」Basic Level 1072 开学寄语 (问题分析+完整步骤+伪代码描述+提交通过代码)

    乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范.从小白开始逐步掌握用编程解决问题. PAT乙级BasicLevelPractice 1072 开学寄语 问题分析 题设要求查找学 ...

  10. 「PAT乙级真题解析」Basic Level 1053 住房空置率 (问题分析+完整步骤+伪代码描述+提交通过代码)

    乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范.从小白开始逐步掌握用编程解决问题. PAT乙级BasicLevelPractice 1053 问题分析 题设要求统计符合住房空置 ...

最新文章

  1. Java面试技巧—如何自我介绍
  2. kd树介绍(KNN算法引出)
  3. 使用OpenSSL工具制作X.509证书的方法及其注意事项总结
  4. 控制台输出HelloWorld案例
  5. SpringBoot中yaml配置
  6. POJ 1037 DP
  7. iphone全部机型_iPhone 上新,首次明确支持中国北斗
  8. Oracle的一些简单用法
  9. 高级java技术栈图
  10. 固定链接设置朴素正常html无法显示,wordpress固定链接设置修改常见问题
  11. 新加坡政府设立网络安全实验室
  12. 不属于计算机完成科学特点的是,2019年网络教育统考《计算机应用基础》试卷版练习题2...
  13. 薛之谦丨当初不以他盛名而来,如今也不会因为诋毁而离开
  14. 【FCPX插件】56种标题文本输入逐字出现字幕打字机动画效果 Typing Titles,支持M1芯片!
  15. 《逆袭大学——传给IT学子的正能量》目录
  16. 2020湖南大学ACM新生杯题解- D Treasure Cave
  17. SRE(运维)最重要的是什么,看这一篇就够了
  18. 关于Java中抽象类和接口的一点思索
  19. 论文查重格式有什么影响?
  20. 广东财经大学计算机自考科目,广东财经大学自考会计本科(120203K)专业介绍及考试计划...

热门文章

  1. 基于ResNet迁移学习的LFW人脸识别分类
  2. 编程语言难度排名_文言文可编程乎?CMU中国大四学生:开源文言文编程语言获1万+标星...
  3. 软件需求说明书/ 概要设计说明书/项目开发计划/详细设计说明书(说明要点及要点解释)
  4. Hacker Rank 上的 Even Tree 小议
  5. 计算机二级报名省市,计算机二级报名通知:全国19省市报名时间及考试安排!...
  6. 数据结构视频教程 -《小甲鱼全套教程之C C++数据结构系列教程》
  7. 三维人脸重建:精读3dmm.py
  8. 网络安全web渗透技术
  9. OpenCV实现同态滤波
  10. 高等数学(第七版)同济大学 习题4-4(后14题) 个人解答