java编程强化练习(三)

1.双链表

【问题描述】输入N(3≤N≤10)个数,依次将这些数插入到结构为
typedef struct _tagDList {
   int data;
   struct _tagDList *pPre, *pNext;
} DLIST;
的双链表表头;再输入一个数num,从链表中删除值为num的结点。
【输入文件】从文件dlist.in读取输入。
第一行是一个数字n(3≤n≤10),代表双链表的结点数。
第二行是n个数字,代表各结点的数值,中间以空格间隔。
第三行是一个数字,代表将要删除的结点的数值。
【输出文件】将操作后链表结点值输出到文件dlist.out,如果链表为空,输出-1。
【输入样例】
8
12 34 56 6 8 12 67
34
【输出样例】
67 12 8 6 56 12
【样例说明】删除链表中值为34的节点后链表节点输出值为67 12 8 6 56 12
【评分标准】结果正确则该测试点得满分,否则该测试点得0分。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.StringTokenizer;

class DList {
    int data;
    DList pPre;
    DList pNext;

    DList(int data) {
        this.data = data;
        pPre = null;
        pNext = null;
    }
}

public class DListOperations {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("dlist.in"));
        int n = Integer.parseInt(br.readLine());
        StringTokenizer st = new StringTokenizer(br.readLine());
        DList head = new DList(Integer.parseInt(st.nextToken()));
        DList tail = head;

        for (int i = 1; i < n; i++) {
            int data = Integer.parseInt(st.nextToken());
            DList newNode = new DList(data);
            newNode.pPre = tail;
            tail.pNext = newNode;
            tail = newNode;
        }

        int numToDelete = Integer.parseInt(br.readLine());
        br.close();

        DList current = head;
        while (current != null) {
            if (current.data == numToDelete) {
                if (current.pPre != null) {
                    current.pPre.pNext = current.pNext;
                } else {
                    head = current.pNext;
                    if (head != null) {
                        head.pPre = null;
                    }
                }

                if (current.pNext != null) {
                    current.pNext.pPre = current.pPre;
                }
            }
            current = current.pNext;
        }

        DList reversedHead = reverseList(head);

        FileWriter fw = new FileWriter("dlist.out");
        if (reversedHead == null) {
            fw.write("-1\n");
        } else {
            current = reversedHead;
            while (current != null) {
                fw.write(current.data + " ");
                current = current.pNext;
            }
            fw.write("\n");
        }
        fw.close();
    }

    private static DList reverseList(DList head) {
        DList current = head;
        DList newHead = null;

        while (current != null) {
            DList temp = current.pNext;
            current.pNext = newHead;
            current.pPre = null;
            if (newHead != null) {
                newHead.pPre = current;
            }
            newHead = current;
            current = temp;
        }

        return newHead;
    }
}

2.中缀转后缀

【问题描述】编写一个程序,把由单个数字的整数组成的一般的中缀表达式(假定键入的是一个正确的表达式)转化成一个后缀表达式。
【输入形式】输入一个合法的中缀表达式(不含空格),以回车符结束输入。表达式中字符个数不超过80个。
【输出形式】输出后缀表达式。
【样例输入】
(6+2)*5-8/4
【样例输出】
62*5*84/-
【样例说明】输入合法的中缀表达式(不含空格),输出后缀表达式。
【评分标准】该题要求输出后缀表达式,答对则该测试点得满分,否则得0分。上传C语言源程序,以express.c命名。

#include 
#include 

typedef struct {
    char *array;
    int top;
} Stack;

void initStack(Stack *stack, int size) {
    stack->array = (char *)malloc(size * sizeof(char));
    stack->top = -1;
}

void push(Stack *stack, char item) {
    stack->array[++(stack->top)] = item;
}

char pop(Stack *stack) {
    return stack->array[(stack->top)--];
}

char peek(Stack *stack) {
    return stack->array[stack->top];
}

int isOperator(char ch) {
    return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}

int getPriority(char ch) {
    if (ch == '+' || ch == '-')
        return 1;
    else if (ch == '*' || ch == '/')
        return 2;
    return 0;
}

void infixToPostfix(char *infix, char *postfix) {
    Stack stack;
    initStack(&stack, 80);

    int i = 0, j = 0;

    while (infix[i] != '\0') {
        char current = infix[i];

        if (isOperator(current)) {
            while (stack.top >= 0 && getPriority(peek(&stack)) >= getPriority(current))
                postfix[j++] = pop(&stack);

            push(&stack, current);
        } else if (current == '(') {
            push(&stack, current);
        } else if (current == ')') {
            while (stack.top >= 0 && peek(&stack) != '(')
                postfix[j++] = pop(&stack);

            pop(&stack); // 弹出 '('
        } else {
            postfix[j++] = current;
        }

        i++;
    }

    while (stack.top >= 0)
        postfix[j++] = pop(&stack);

    postfix[j] = '\0';
}

int main() {
    char infix[80];
    char postfix[80];

    scanf("%s", infix);

    infixToPostfix(infix, postfix);

    printf("%s\n", postfix);

    return 0;
}

3.全排列数的生成

【问题描述】输入整数N( 1 <= N <= 10 ),生成从1~N所有整数的全排列。
【输入形式】输入整数N。
【输出形式】输出有N!行,每行都是从1~N所有整数的一个全排列,各整数之间以空格分隔。各行上的全排列不重复。输出各行遵循“小数优先”原则, 在各全排列中,较小的数尽量靠前输出。如果将每行上的输出看成一个数字,则所有输出构成升序数列。具体格式见输出样例。
【样例输入1】1
【样例输出1】1
【样例说明1】输入整数N=1,其全排列只有一种。
【样例输入2】3 
【样例输出2】
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
【样例说明2】输入整数N=3,要求整数1、2、3的所有全排列, 共有N!=6行。且先输出1开头的所有排列数,再输出2开头的所有排列数,最后输出3开头的所有排列数。在以1开头的所有全排列中同样遵循此原则。
【样例输入3】10
【样例输出3】
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 10 9
1 2 3 4 5 6 7 9 8 10
1 2 3 4 5 6 7 9 10 8
1 2 3 4 5 6 7 10 8 9
1 2 3 4 5 6 7 10 9 8
1 2 3 4 5 6 8 7 9 10
1 2 3 4 5 6 8 7 10 9
1 2 3 4 5 6 8 9 7 10
1 2 3 4 5 6 8 9 10 7
……………………
【样例说明3】输入整数N=10,要求整数1、2、3、……、10的所有全排列。上例显示了输出的前10行。
【运行时限】要求每次运行时间限制在20秒之内。超出该时间则认为程序错误。提示:当N增大时,运行时间将急剧增加。在编程时要注意尽量优化算法,提高运行效率。
【评分标准】该题要求输出若干行整数。。

import java.util.*;

public class Permutations {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        int n = scanner.nextInt();
        int[] nums = new int[n];
        for (int i = 1; i <= n; i++) {
            nums[i - 1] = i;
        }
        List> permutations = permute(nums);
        for (List permutation : permutations) {
            for (int num : permutation) {
                System.out.print(num + " ");
            }
            System.out.println();
        }
    }

    public static List> permute(int[] nums) {
        List> permutations = new ArrayList<>();
        List current = new ArrayList<>();
        boolean[] used = new boolean[nums.length];
        dfs(nums, used, current, permutations);
        return permutations;
    }

    private static void dfs(int[] nums, boolean[] used, List current, List> permutations) {
        if (current.size() == nums.length) {
            permutations.add(new ArrayList<>(current));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (!used[i]) {
                used[i] = true;
                current.add(nums[i]);
                dfs(nums, used, current, permutations);
                current.remove(current.size() - 1);
                used[i] = false;
            }
        }
    }
}

4.矩阵旋转

【问题描述】输入矩阵阶数n,给n阶矩阵的元素按行序由1到n*n顺序赋值,然后将其向右旋转90度,输出旋转后的矩阵。
【输入形式】控制台输入阶数n。
【输出形式】输出旋转90度后的矩阵,其中每个数字占4位字符的宽度,向右对齐。
【样例输入】
4
【样例输出】
  13   9   5   1

  14  10   6   2

  15  11   7   3

  16  12   8   4
【样例说明】输入整数n = 4,输出旋转后的矩阵。
【评分标准】该题要求输出旋转后的矩阵,答对则该测试点得满分,否则得0分。

import java.util.Scanner;

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

        int[][] matrix = new int[n][n];
        int num = 1;

        // 按行序由1到n*n顺序赋值
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                matrix[i][j] = num++;
            }
        }

        // 将矩阵向右旋转90度
        int[][] rotatedMatrix = rotateMatrix(matrix);

        // 输出旋转后的矩阵
        for (int[] row : rotatedMatrix) {
            for (int element : row) {
                System.out.printf("%4d", element);
            }
            System.out.println();
        }
    }

    public static int[][] rotateMatrix(int[][] matrix) {
        int n = matrix.length;
        int[][] rotatedMatrix = new int[n][n];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                rotatedMatrix[j][n - 1 - i] = matrix[i][j];
            }
        }

        return rotatedMatrix;
    }
}

5.学生成绩排序

【问题描述】
对某班学生成绩排序。从键盘依次输入某班学生的姓名和成绩(一个班级人数最多不超过50人)并保存,然后分别按学生成绩由高到低顺序输出学生姓名和成绩,成绩相同时,则按输入次序排序。
【输入形式】
从键盘依次输入最多不超过50个学生的学生姓名和成绩:
第一行输入班级学生人数;
在单独行上输入空格隔开的学生姓名和成绩,其中学生成绩是整数。
【输出形式】
按学生成绩由高到低顺序输出学生姓名和成绩,每行输出一位学生的姓名和成绩,其中姓名(英文)占15位,成绩占5位,均按缺省方式对齐。成绩相同时按输入次序排序。
【输入样例】
4
aaa 50
bbb 70
ccc 65
ddd 90
【输出样例】

############ddd###90
############bbb###70
############ccc###65
############aaa###50

(注意:其中“#”号代表空格)

【样例说明】
输入了四个学生姓名和成绩,按成绩排序输出。
【评分标准】
按成绩顺序输出学生姓名和成绩,完全正确得50分,共五个测试点,每个测试点10分。

import java.util.*;

public class StudentGradeSorting {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int numStudents = scanner.nextInt();
        scanner.nextLine(); // 读取换行符

        List students = new ArrayList<>();

        for (int i = 0; i < numStudents; i++) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ");
            String name = parts[0];
            int grade = Integer.parseInt(parts[1]);
            students.add(new Student(name, grade));
        }

        // 按成绩由高到低排序
        Collections.sort(students, new Comparator() {
            @Override
            public int compare(Student s1, Student s2) {
                if (s1.getGrade() == s2.getGrade()) {
                    // 成绩相同时按输入次序排序
                    return Integer.compare(students.indexOf(s1), students.indexOf(s2));
                } else {
                    return Integer.compare(s2.getGrade(), s1.getGrade());
                }
            }
        });

        // 输出学生姓名和成绩
        for (Student student : students) {
            String name = student.getName();
            int grade = student.getGrade();
            System.out.printf("%15s%5d\n", name, grade);
        }
    }

   
}

class Student {
    private String name;
    private int grade;

    public Student(String name, int grade) {
        this.name = name;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public int getGrade() {
        return grade;
    }
}

6. 删除字符串(新)

【问题描述】

编写程序将一个指定文件中给定字符串删除。假设给定的字符串长度不超过20,文件中每行的字符数不超过100。要求:给定的字符串大小写无关。

【输入形式】

给定文件名为filein.txt。从标准输入中输入要删除的字符串(不含空格)。

【输出形式】

将删除后的结果输出到文件fileout.txt中。

【样例输入】

从标准输入中输入要删除的字符串:

in

文件filein.txt的内容为:

#include

void main()

{

    FILE * IN;

    if((IN=fopen("in.txt","r"))==NULL)

    {

       printf("Can’t open in.txt!");

       return;

    }

    fclose(IN);

}

【样例输出】

文件fileout.txt的内容应为:

#clude

void ma()

{

    FILE * ;

    if((=fopen(".txt","r"))==NULL)

    {

       prtf("Can’t open .txt!");

       return;

    }

    fclose();

}

【样例说明】

输入的要删除的字符串为in,即将文件filein.txt中所有出现的in字符串(包括iN、In、IN字符串)删除,然后将删除后的文件内容输出保存在文件fileout.txt中。

【评分标准】

该题要求得到删除给定字符串后的文件内容。

import java.io.*;

public class StringDeletion {
    public static void main(String[] args) {
        try {
            // 从标准输入读取要删除的字符串
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String stringToDelete = reader.readLine();

            // 读取输入文件
            BufferedReader inputFileReader = new BufferedReader(new FileReader("filein.txt"));

            // 创建输出文件
            BufferedWriter outputFileWriter = new BufferedWriter(new FileWriter("fileout.txt"));

            String line;
            while ((line = inputFileReader.readLine()) != null) {
                // 删除字符串(不区分大小写)
                String updatedLine = line.replaceAll("(?i)" + stringToDelete, "");

                // 写入更新后的行到输出文件
                outputFileWriter.write(updatedLine);
                outputFileWriter.newLine();
            }

            // 关闭文件读写器
            inputFileReader.close();
            outputFileWriter.close();

            System.out.println("文件处理完成。");

        } catch (IOException e) {
            System.out.println("发生IO异常: " + e.getMessage());
        }
    }
}

7.

  1. 科学计数法与小数形式转换

【问题描述】

编写一个程序,将用科学计数法输入的一个数转换成小数表示的形式输出。该科学计数法表示的数字由以下几部分构成:
1.底数部分是一个小数,小数点前后必有数字,而且都为有效数字。即:小数点前只有一位大于0的数字,小数点后的末尾数字不能为0。底数前没有表示符号的“+”、“-”字符。
2.必有字母“e”或“E”。
3.指数部分是一个整数(小于100),也可能带有前缀的“+”、“-”号。
注意:转换后小数点后应均为有效数字,即末尾不含数字0,若无有效数字,则不输出小数点。

提示:可按字符串形式存储相关数据。

【输入形式】

控制台输入用科学计数法表示的一个数,其是一个不含空格的字符串,字符个数不会超过50,最后会有回车换行符。

【输出形式】

以小数形式输出该科学计数法表示的数。

【输入样例1】

2.569e-8

【输出样例1】

0.00000002569

【输入样例2】

8.9845623489650017659e5

【输出样例2】

898456.23489650017659

【输入样例3】

3.67298599990099E+42

【输出样例3】

3672985999900990000000000000000000000000000

【样例说明】

以科学计数法输入数据,然后转换后以小数形式输出,注意:样例3中输入的数据转换后无小数部分,小数点就不再输出。

【评分标准】

该题要求以小数点形式输出数据。

import java.math.BigDecimal;
import java.util.Scanner;

public class ScientificToDecimal {
    public static void main(String[] args) {
        // 从控制台读取输入
        Scanner scanner = new Scanner(System.in);
        String scientificNotation = scanner.nextLine();

        // 将科学计数法表示的数转换为小数形式
        String decimalNumber = convertScientificToDecimal(scientificNotation);

        // 输出结果
        System.out.println(decimalNumber);
    }

    private static String convertScientificToDecimal(String scientificNotation) {
        // 判断科学计数法是否有效
        if (!scientificNotation.matches("^[+-]?\\d+(\\.\\d+)?[eE][+-]?\\d+$")) {
            return "Invalid scientific notation";
        }

        // 使用BigDecimal进行高精度运算
        BigDecimal number = new BigDecimal(scientificNotation);

        // 转换为小数形式
        return number.toPlainString();
    }
}

8.排序问题

【问题描述】从键盘终端输入若干整数(不超过50个),将其中的基数按从小到大原地排序(奇数递增排序,偶数原地不变),输出排序后的结果。

【输入形式】二行,第一行:整数个数,第二行:待排序整数

【输出形式】按规则排序后的整数以空格间隔输出

【样例输入】

20

76 14 63 79 64 18 11 29 54 20 63 90 29 18 79 36 84 10 45 89

【样例输出】76 14 11 29 64 18 29 45 54 20 63 90 63 18 79 36 84 10 79 89

【样例说明】

【评分标准】

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class OddNumberSort {
    public static void main(String[] args) {
        // 从控制台读取输入
        Scanner scanner = new Scanner(System.in);

        // 读取整数个数
        int count = scanner.nextInt();
        scanner.nextLine(); // 读取换行符

        // 读取待排序整数
        String input = scanner.nextLine();

        // 将待排序整数转换为数组
        String[] numbers = input.split(" ");

        // 转换为整数列表
        List oddNumbers = new ArrayList<>();
        for (String number : numbers) {
            int value = Integer.parseInt(number);
            if (value % 2 == 1) {
                oddNumbers.add(value);
            }
        }

        // 对奇数进行排序
        Collections.sort(oddNumbers);

        // 替换原数组中的奇数部分
        int index = 0;
        for (int i = 0; i < numbers.length; i++) {
            int value = Integer.parseInt(numbers[i]);
            if (value % 2 == 1) {
                numbers[i] = oddNumbers.get(index).toString();
                index++;
            }
        }

        // 输出排序结果
        for (String number : numbers) {
            System.out.print(number + " ");
        }
    }
}

9.验证哥德巴赫猜想

【问题描述】验证哥德巴赫猜想:输入一个大于2的偶数,将其分解为两个素数的和

【输入形式】8
【输出形式】8=3+5
【样例输入】
【样例输出】
【样例说明】
【评分标准】

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class GoldbachConjecture {
    public static void main(String[] args) {
        // 从控制台读取输入
        Scanner scanner = new Scanner(System.in);
        int number = scanner.nextInt();

        // 验证哥德巴赫猜想
        if (number <= 2 || number % 2 != 0) {
            System.out.println("输入错误,请输入一个大于2的偶数。");
        } else {
            List primes = findPrimes(number);
            if (primes.isEmpty()) {
                System.out.println("无法找到两个素数使得它们的和等于" + number);
            } else {
                System.out.println(number + "=" + primes.get(0) + "+" + primes.get(1));
            }
        }
    }

    private static List findPrimes(int number) {
        List primes = new ArrayList<>();
        boolean[] isComposite = new boolean[number + 1];

        for (int i = 2; i <= number; i++) {
            if (!isComposite[i]) {
                for (int j = i * i; j <= number; j += i) {
                    isComposite[j] = true;
                }
                if (isPrime(number - i)) {
                    primes.add(i);
                    primes.add(number - i);
                    break;
                }
            }
        }

        return primes;
    }

    private static boolean isPrime(int number) {
        if (number <= 1) {
            return false;
        }

        for (int i = 2; i <= Math.sqrt(number); i++) {
            if (number % i == 0) {
                return false;
            }
        }

        return true;
    }
}

10.特殊四位数

【问题描述】四位数3025有一个特殊性质:它的前两位数字30和后两位数字25的和是 55,而55的平方刚好等于该数(55*55=3025)。试编一程序打印所有具有这种性质的四位数。
【输入形式】
【输出形式】
【样例输入】
【样例输出】
【样例说明】
【评分标准】

public class SpecialNumbers {
    public static void main(String[] args) {

        for (int number = 1000; number < 10000; number++) {
            int firstTwoDigits = number / 100;
            int lastTwoDigits = number % 100;
            if (Math.pow((firstTwoDigits + lastTwoDigits), 2) == number) {
                System.out.print(number+" ");
            }
        }
    }
}

11.整数出现次数

【问题描述】

输入一组无序的整数,编程输出其中出现次数最多的整数及其出现次数。

【输入形式】

先从标准输入读入整数的个数(大于等于1,小于等于100),然后在下一行输入这些整数,各整数之间以一个空格分隔。

【输出形式】

在标准输出上输出出现次数最多的整数及其出现次数,两者以一个空格分隔;若出现次数最多的整数有多个,则按照整数升序分行输出。

【样例输入】

10

0 -50 0 632 5813 -50 9 -50 0 632

【样例输出】

-50 3

0 3

【样例说明】

输入了10个整数,其中出现次数最多的是-50和0,都是出现3次。

【评分标准】该程序要求输出出现次数最多的整数和出现次数。

import java.util.*;

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

        int count = scanner.nextInt();
        
        Map frequencyMap = new HashMap<>();
        for (int i = 0; i < count; i++) {
            int number = scanner.nextInt();
            frequencyMap.put(number, frequencyMap.getOrDefault(number, 0) + 1);
        }

        int maxFrequency = Collections.max(frequencyMap.values());
        List mostFrequentNumbers = new ArrayList<>();
        for (int number : frequencyMap.keySet()) {
            if (frequencyMap.get(number) == maxFrequency) {
                mostFrequentNumbers.add(number);
            }
        }

        Collections.sort(mostFrequentNumbers);


        for (int number : mostFrequentNumbers) {
            System.out.println(number + " " + maxFrequency);
        }
    }
}

12.计算n个a相减

【问题描述】

输入两个整数a(大于等于1且小于等于9)和n(大于等于1且小于等于80),编程求得并输出下面等式的值:

例如:若输入的a为5,n为6,则要计算下面公式的值:

555555-55555-5555-555-55-5。

【输入形式】

从标准输入读入整数a和n,两者之间以一个空格分隔。

【输出形式】

在标准输出上输出公式的计算结果。

【样例1输入】

5 6

【样例1输出】

493830

【样例1说明】

输入的a为5,n为6,按照上述公式计算的结果为493830。

【样例2输入】

5 20

【样例2输出】

49382716049382716060

【样例2说明】

输入的a为5,n为20,按照上述公式计算的结果为49382716049382716060。

【评分标准】该程序要求输出求得的公式的值。

import java.util.Scanner;
import java.math.BigInteger;

public class FormulaCalculation {
    public static BigInteger fun(long a, long n) {
        if (a < 1 || a > 9 || n < 1 || n > 80)
            return BigInteger.valueOf(-1);

        BigInteger r = BigInteger.valueOf(0);
        BigInteger ans;
        for (long i = 0; i < n; i++) {
            r = r.multiply(BigInteger.TEN).add(BigInteger.valueOf(a));
        }
        ans = r;
        r = r.divide(BigInteger.TEN);//表示一个 BigInteger 对象,它等于整数值 10
        while (r.compareTo(BigInteger.ZERO) > 0) {
            ans = ans.subtract(r);
            r = r.divide(BigInteger.TEN);
        }
        return ans;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long a = scanner.nextInt();
        long n = scanner.nextInt();
        scanner.close();
        BigInteger ans = fun(a, n);
        System.out.println(ans);
    }
}

你可能感兴趣的:(java,算法,开发语言)