Java编程强化练习(二)

  1. 表达式计算(支持空格,连乘,连除)(选做题,不计分)

【问题描述】

从标准输入中读入一个整数算术运算表达式,如5 - 1 * 2 * 3 + 12 / 2 / 2  = 。计算表达式结果,并输出。

要求:
1、表达式运算符只有+、-、*、/,表达式末尾的’=’字符表示表达式输入结束,表达式中可能会出现空格;
2、表达式中不含圆括号,不会出现错误的表达式;
3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。

【输入形式】

在控制台中输入一个以’=’结尾的整数算术运算表达式。

【输出形式】

向控制台输出计算结果(为整数)。

【样例1输入】

5 - 1 * 2 * 3 + 12 / 2 / 2  =

【样例1输出】

2

【样例2输入】

500 =

【样例2输出】

500

【样例1说明】

输入的表达式为5 - 1 * 2 * 3 + 12 / 2 / 2 =,按照整数运算规则,计算结果为2,故输出2。

【样例2说明】

输入的表达式为500 = ,没有运算符参与运算,故直接输出500。

算法之一提示:
1、可以利用gets函数,读取整行表达式;
2、对于空格,可以考虑首先去除表达式中的所有空格
3、可以设一计数器用来记录已读取、但未参加运算的运算符的个数,根据该计数器来判断如何进行运算;
4、可以设计一函数:实现二元整数算术运算。

import java.util.Scanner;
import java.util.Scanner;
import java.util.Stack;

public class ArithmeticExpression {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String expression = scanner.nextLine();

        int result = evaluateExpression(expression);
        System.out.println( result);
    }

    private static boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/';
    }

    private static int getPrecedence(char op) {
        if (op == '+' || op == '-')
            return 1;
        if (op == '*' || op == '/')
            return 2;
        return 0;
    }

    private static int applyOperation(int num1, int num2, char op) {
        switch (op) {
            case '+':
                return num1 + num2;
            case '-':
                return num1 - num2;
            case '*':
                return num1 * num2;
            case '/':
                return num1 / num2;
            default:
                return 0;
        }
    }

    private static int evaluateExpression(String expression) {
        Stack operands = new Stack<>();
        Stack operators = new Stack<>();

        for (int i = 0; i < expression.length(); i++) {
            char c = expression.charAt(i);

            if (Character.isWhitespace(c))
                continue;

            if (Character.isDigit(c)) {
                int num = c - '0';
                while (i + 1 < expression.length() && Character.isDigit(expression.charAt(i + 1))) {
                    num = num * 10 + (expression.charAt(i + 1) - '0');
                    i++;
                }
                operands.push(num);
            } else if (c == '(') {
                operators.push(c);
            } else if (c == ')') {
                while (!operators.isEmpty() && operators.peek() != '(') {
                    int num2 = operands.pop();
                    int num1 = operands.pop();
                    char op = operators.pop();
                    int result = applyOperation(num1, num2, op);
                    operands.push(result);
                }
                operators.pop(); // 弹出左括号
            } else if (isOperator(c)) {
                while (!operators.isEmpty() && isOperator(operators.peek()) && getPrecedence(operators.peek()) >= getPrecedence(c)) {
                    int num2 = operands.pop();
                    int num1 = operands.pop();
                    char op = operators.pop();
                    int result = applyOperation(num1, num2, op);
                    operands.push(result);
                }
                operators.push(c);
            }
        }

        while (!operators.isEmpty()) {
            int num2 = operands.pop();
            int num1 = operands.pop();
            char op = operators.pop();
            int result = applyOperation(num1, num2, op);
            operands.push(result);
        }

        return operands.pop();
    }
}

2.合并数列

【问题描述】从标准输入上读入2N行(行号从0开始)由空格分隔的整数,并顺序将第2i和2i+1行(0 <= i <= N)合并成一个由小到大排好序并删除重复数字的数列,写在标准输出上,每个数列一行。每一个原始数列不超过50个数字。
【输入形式】输入2N行整数,每行对应一个数列。每行有k个数字,是属于这一数列的所有整数,由空格分隔。这些整数随机排列,并可能含有重复数字。程序的任务就是将每两个相邻的数列合并成一个,并且从小到大排序,同时要删除重复数字。
【输出形式】输出有N行,每行有若干个空格分隔的整数,是在输入文件中对应两个输入行的合并结果。并且:
1.这些数字已经从小到大排序。
2.不含重复数字。
【样例输入】
18 29 30 27 26
20 30 5 29
76 80
99 233 87 35 24 9
27 234 27
65 70 39 87 35 24 100
【样例输出】
5 18 20 26 27 29 30
9 24 35 76 80 87 99 233
24 27 35 39 65 70 87 100 234
【样例说明】输入共有6行整数。第一个数列含5个整数,分别是18、29、30、27、26。依次类推,第二个数列含4个整数,第三个数列含2个整数,……,第六个数列含7个整数。输出共有三行数字。输出的第一行是将原输出的第一、二个数列合并,同时删除重复数字并从小到大排序的结果。输出的第二行是将原输出的第三、四个数列合并,同时删除重复数字并从小到大排序的结果。输出的第三行是将原输出的第五、六个数列合并,同时删除重复数字并从小到大排序的结果。
【运行时限】要求每次运行时间限制在10秒之内。超出时间则认为程序错误。
【评分标准】输出的数字中。如果你的程序计算的完全正确,该测试点得10分,否则算该测试点得分为0。

import java.util.*;

public class MergeAndSort {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        List> result = new ArrayList<>();

        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            if (line.isEmpty()) {
                break;
            }

            List line1 = parseLine(line);
            if (!scanner.hasNextLine()) {
                // 如果只有单独的一行,直接输出该行而不进行合并
                result.add(line1);
                break;
            }

            List line2 = parseLine(scanner.nextLine());

            if (line1.isEmpty() || line2.isEmpty()) {
                // 如果其中一行为空,直接输出非空的行
                if (!line1.isEmpty()) {
                    result.add(line1);
                }
                if (!line2.isEmpty()) {
                    result.add(line2);
                }
            } else {
                List merged = mergeAndSort(line1, line2);
                result.add(merged);
            }
        }

        for (List mergedList : result) {
            Collections.sort(mergedList); // 对每一行进行排序
            for (int num : mergedList) {
                System.out.print(num + " ");
            }
            System.out.println();
        }
    }

    private static List parseLine(String line) {
        List numbers = new ArrayList<>();
        String[] tokens = line.split(" ");

        for (String token : tokens) {
            numbers.add(Integer.parseInt(token));
        }

        return numbers;
    }

    private static List mergeAndSort(List list1, List list2) {
        Set set = new TreeSet<>();
        set.addAll(list1);
        set.addAll(list2);

        return new ArrayList<>(set);
    }
}

3.计算星期

【问题描述】
已知1980年1月1日是星期二。
任意输入一个日期,求这一天是星期几。
【输入形式】
从键盘输入一行字符串“Y-M-D”,是一个有效的公历日期。其中Y为年(1980≤Y≤3000),M为月,D为天,都不带有前缀0。
【输出形式】
在屏幕输出结果。
输出只有一行,是代表该日星期的字符串。对于星期一至星期日,分别输出Monday、Tuesday、Wednesday、Thursday、Friday、Saturday、Sunday。在行末要输出一个回车符。判断闰年的算法是:

年份能被4整除并且不能被100整除,或者能被四百整除。
【输入样例】
2004-1-6
【输出样例】
Tuesday
【评分标准】
本题不准使用数学库函数。运行时限1秒。结果完全正确得20分,每个测试点4分。

import java.util.Scanner;

public class CalculateWeekday {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();

        String[] tokens = input.split("-");
        int year = Integer.parseInt(tokens[0]);
        int month = Integer.parseInt(tokens[1]);
        int day = Integer.parseInt(tokens[2]);

        int weekday = calculateWeekday(year, month, day);
        String weekdayString = getWeekdayString(weekday);
        System.out.println(weekdayString);
    }

    private static int calculateWeekday(int year, int month, int day) {
        // 计算从1980年1月1日到目标日期的总天数
        int days = calculateTotalDays(year, month, day);

        // 1980年1月1日是星期二,因此计算星期数时需要加上偏移量
        int offset = 2;

        // 对7取模,得到星期几的数值(0代表星期一,1代表星期二,以此类推)
        int weekday = ( days) % 7;

        return weekday;
    }

    private static int calculateTotalDays(int year, int month, int day) {
        // 每个月的天数
        int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        // 判断是否为闰年,并更新2月的天数
        if (isLeapYear(year)) {
            daysInMonth[1] = 29;
        }

        int totalDays = 0;

        // 计算整年的天数
        for (int i = 1980; i < year; i++) {
            if (isLeapYear(i)) {
                totalDays += 366;
            } else {
                totalDays += 365;
            }
        }

        // 计算当年的天数
        for (int i = 0; i < month - 1; i++) {
            totalDays += daysInMonth[i];
        }

        totalDays += day;

        return totalDays;
    }

    private static boolean isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }

    private static String getWeekdayString(int weekday) {
        String[] weekdays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
        return weekdays[weekday];
    }
}
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;

public class CalculateWeekday {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d");
        LocalDate date = LocalDate.parse(input, formatter);
        DayOfWeek weekday = date.getDayOfWeek();
        String weekdayString = weekday.toString();

        System.out.println(weekdayString);
    }
}
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Scanner;

public class CalculateWeekday {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();

        String[] tokens = input.split("-");
        int year = Integer.parseInt(tokens[0]);
        int month = Integer.parseInt(tokens[1]);
        int day = Integer.parseInt(tokens[2]);

        LocalDate date = LocalDate.of(year, month, day);
        DayOfWeek weekday = date.getDayOfWeek();
        String weekdayString = weekday.toString().substring(0, 1) + weekday.toString().substring(1).toLowerCase();

        System.out.println(weekdayString);
    }
}

4、比较两组整数

【问题描述】
比较两组整数是否有相同的元素,不考虑元素的顺序,并忽略元素重复的情况。例如:
1  4  9  16  9  7  4  9  11
与下列一组整数:
11  7  9  16  4  1
相同。
【输入形式】
分行输入两组整数,以空格分割
【输出形式】
打印两组整数中相同的元素,顺序以第一行的整数输出顺序为准,如果没有相同元素,打印“No Answer”
【输入样例】
1 4  9  16  9  7  4  9  11
11  7  9  16  4  1
【输出样例】

"#"代表空格
1#4#9#16#7#11#
【样例说明】
输入两组整数
1  4  9  16  9  7  4  9  11
11  7  9  16  4  1
由于这两个数组具有相同的元素,顺序打印第一行与第二行相同的元素

【评分标准】
该题要求输出相同元素,答对得20分,每个测试点4分。

import java.util.*;

public class CompareIntegers {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input1 = scanner.nextLine();
        String input2 = scanner.nextLine();

        String[] nums1 = input1.split(" ");
        String[] nums2 = input2.split(" ");

        Set set1 = new LinkedHashSet<>(Arrays.asList(nums1));
        Set set2 = new HashSet<>(Arrays.asList(nums2));

        set1.retainAll(set2);

        if (set1.isEmpty()) {
            System.out.println("No Answer");
        } else {
            StringBuilder output = new StringBuilder();
            for (String num : nums1) {
                if (set1.contains(num)) {
                    output.append(num).append(" ");
                    set1.remove(num);
                }
            }
            output.deleteCharAt(output.length() - 1);
            System.out.println(output.toString());
        }
    }
}

5、字符串匹配

问题描述】利用“通配符”,可以用简单的方法标记一组字符串。
通配符有两个,“?”代表一个任意字符,“*”代表0个或多个任意字符。
例如:
AB?.txt可以表示AB1.txt,AB2.txt,ABa.txt 等。
AB*.txt可以表示AB.txt, AB1.txt,AB332.txt,ABaa.txt等。
编写程序,判断一个字符串是否符合一个含有通配符的串。
【输入文件】从文件match.in读取输入。
第一行是一个串,含有通配符“?”或“*”,或两者兼有。
第二行是一个数字n(3≤n≤10),代表后续有n个待检验串。
后面的n行,每行有一个不含通配符的待检验串。
输入中的所有串均只包含英文字母(大小写)和数字,不含空格,长度在80字符以内。
【输出文件】输出到文件match.out中。将所有符合的串按原顺序分行打印。在每一行末均输出一个回车符。
【输入样例】
abcd?123*
4
abce123
abcda12345
abcda123
1234
【输出样例】
abcda12345
abcda123
【样例说明】abcda12345和abcda123符合abcd?123*的顺序。
【评分标准】结果正确则该测试点得满分,否则该测试点得0分。上传c语言源程序为match.c。

import java.util.Scanner;
 
public class everydayjava {
    public static boolean matchPattern(String pattern, String text) {
        int m = pattern.length();
        int n = text.length();
 
        boolean[][] a = new boolean[m + 1][n + 1];
        a[0][0] = true;
 
        for (int i = 1; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                if (pattern.charAt(i - 1) == '*') {
                    a[i][j] = a[i - 1][j] || (j > 0 && a[i][j - 1]);
                } else if (j > 0 && (pattern.charAt(i - 1) == '?' || pattern.charAt(i - 1) == text.charAt(j - 1))) {
                    a[i][j] = a[i - 1][j - 1];
                }
            }
        }
 
        return a[m][n];
    }
 
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
 
        System.out.print("请输入测试判断模板: ");
        String pattern = scanner.nextLine();
 
        System.out.print("请输入测试数据的个数: ");
        int n = scanner.nextInt();
        scanner.nextLine();
        System.out.println("请输入用于测试的字符串:");
 
        for (int i = 0; i < n; i++) {
            String text = scanner.nextLine();
            if (matchPattern(pattern, text)) {
                System.out.println(text);
            }
        }
 
        scanner.close();
    }
}

6.将文件中每一行字符反序

【问题描述】对于一个文本文件text1.dat,编写一个程序,将该文件中的每一行字符颠倒顺序后输出到另一个文件text2.dat中。
【输入文件】输入文件为当前目录下的text1.dat,该文件含有多行任意字符,也可能有空行。每个文本行最长不超过80个字符。在最后一行的结尾也有一个回车符。
【输出文件】输出文件为当前目录下的text2.dat。
【样例输入】设输入文件text1.dat为:
This is a test!
Hello, world!
How are you?
【样例输出】输出文件text2.dat为:
!tset a si sihT
!dlrow ,olleH
?uoy era woH
【样例说明】将输入文件反序输出。
【评分标准】输出文件应与输入文件的字符个数相等,并且符合题目规定的格式。如果你的程序输出正确,该测试点得满分,否则该测试点不得分。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class ReverseLines {
    public static void main(String[] args) {
        String inputFile = "text1.dat";
        String outputFile = "text2.dat";

        try (BufferedReader reader = new BufferedReader(new FileReader(inputFile));
             BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {

            String line;
            while ((line = reader.readLine()) != null) {
                String reversedLine = reverseString(line);
                writer.write(reversedLine);
                writer.newLine();
            }

            System.out.println("Reversing lines completed successfully.");

        } catch (IOException e) {
            System.out.println("An error occurred: " + e.getMessage());
        }
    }

    private static String reverseString(String str) {
        StringBuilder reversed = new StringBuilder(str);
        return reversed.reverse().toString();
    }
}

你可能感兴趣的:(算法,数据结构)