ACM模式刷题(Java)

文章目录

  • 一、简单的数组输入
  • 二、构造二叉树(输入)
  • 三、构造数组
  • 四、构造链表
  • 五、二叉树变成数组或者字符串(输出)
  • 六、其他情况
    • 1. 数字+字符串
    • 2. BufferedRead用法
    • 3. 需要定义全局变量
    • 4. 未知多少行输入
  • 典型例子
    • 1. 二叉树:LeetCode删除二叉搜索树的节点(基于Scanner)
    • 2. 链表(基于Scanner)
    • 3. Scanner超时,使用BufferedRead

常规的读输入输出:scanner基本用法
多行输入输出怎么处理
由字符串变数组再变二叉树,以及反过来怎么操作
由字符串变数组再变链表,以及反过来怎么操作
BufferedRead

一、简单的数组输入

[2,7,11,15]
9
import java.util.Scanner;
   //建议直接都写 * ,这样就可以导进来所有包了
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String line = s.nextLine();         //读取字符串
        System.out.println("字符串:"line);
        int a = s.nextInt();                //读取整数
        System.out.println("整数:"+a);
    }
}

二、构造二叉树(输入)

/**
 * 构造树:层序遍历的思想
 * 这都可以当成一道题了...
 */
public class Main {

    private static class TreeNode {    //二叉树类
        int val;
        TreeNode left, right;
        TreeNode() {}
        TreeNode(int val) { this.val = val; }
        TreeNode(int val,TreeNode left,TreeNode right){
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

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

        TreeNode root = StringToTreeNode(str);
        //System.out.println(root.left.val);
    }

    private static TreeNode StringToTreeNode(String str) {
        String[] parts = str
                .substring(1, str.length() - 1)
                .split(",");
    //变成字符串后,逐一处理
        String item = parts[0];
        TreeNode root = new TreeNode(Integer.parseInt(item));    //二叉树的根节点

        Queue<TreeNode> q = new LinkedList<>();    //使用队列添加结点
        q.offer(root);

        int index = 1;
        while (!q.isEmpty()) {
            TreeNode node = q.poll();

            if (index == parts.length) break;

            item = parts[index ++];
            if (!item.equals("null")) {
                node.left = new TreeNode(Integer.parseInt(item));
                q.offer(node.left);
            }

            if (index == parts.length) break;

            item = parts[index ++];
            if (!item.equals("null")) {
                node.right = new TreeNode(Integer.parseInt(item));
                q.offer(node.right);
            }
        }

        return root;
    }
}
//输出
[1,2,3]
2

三、构造数组

/**
 * 构造数组
 */

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        //System.out.println(line);
        int[] nums = StringToIntArray(line);
        //for(int num:nums){
            //System.out.println(num);
        //}
    }
    private static int[] StringToIntArray(String str) {
        String[] parts = str                //根据“,”分割成字符串数组
                .substring(1, str.length() - 1)
                .split(",");
        int[] nums = new int[parts.length];
        for (int i = 0; i < parts.length; i ++)
            nums[i] = Integer.parseInt(parts[i]);    //转为整型数组

        return nums;
    }
}
//输入输出
[1,2,3,4]
[1,2,3,4]
1
2
3
4

四、构造链表

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        System.out.println(line);
        ListNode node = StringToListNode(line);
        System.out.println(node.val);
        System.out.println(node.next.next.next.val);
    }
    private static class ListNode {
         int val;
         ListNode next;
         ListNode() {}
         ListNode(int val) { this.val = val; }
         ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    }
    private static ListNode StringToListNode(String str) {
        String[] parts = str    //分割字符串
                .substring(1, str.length() - 1)
                .split(",");

        ListNode dummy = new ListNode(-1), cur = dummy;        //虚拟头结点

        for (String s: parts) {
            cur.next = new ListNode(Integer.parseInt(s));      //逐个添加链表的结点
            cur = cur.next;
        }

        return dummy.next;    //返回真正的头结点
    }
}

五、二叉树变成数组或者字符串(输出)

/**
 * ACM模式:二叉树 删除搜索二叉树的节点
 * 输入:
 * 5 3 6 2 4 null 7
 * 3
 * 输出:
 * [5,4,6,2,null,null,7]
 * 5 4 6 2 null null 7
 */
public class Solution7 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        int key = sc.nextInt();
        String[] parts = line.split(" ");//字符串变数组
        int len = parts.length;
        TreeNode root = strToTree(parts);//数组变树
        TreeNode res = deleteNode(root,key);//题目的处理逻辑
        //树变数组
        Integer[] nums = new Integer[len];
        treeToArray(nums,res,0);
//        //输出1:[5,4,6,2,null,null,7]
//        System.out.println(Arrays.toString(nums));
        String str = Arrays.toString(nums);
        str = str.substring(1,str.length()-1);
        System.out.println(str.replace(","," "));
    }
        private static void treeToArray(Integer[] arr,TreeNode node,int index){
        if(node==null){
            return;
        }
        arr[index] = node.val;
        treeToArray(arr,node.left,2*index+1);
        treeToArray(arr,node.right,index*2+2);
    }

六、其他情况

1. 数字+字符串

import java.util.Scanner;

/**
 * leetcode 回文子串
 * 输入描述:
 * 2
 * abc
 * aaa
 * 输出描述:
 * 3
 * 6
 */
public class Solution5 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        sc.nextLine();//注意一定要有
        for(int i=0;i<num;i++){
            String str = sc.nextLine();
            int res = countSubString(str);
            System.out.println(res);
        }
    }
    public static int countSubString(String s){
        boolean[][] dp = new boolean[s.length()][s.length()];
        int res = 0;
        for(int i=s.length()-1;i>=0;i--){
            for(int j=i;j<s.length();j++){
                if(s.charAt(i)==s.charAt(j)){
                    if(j-i<=1){
                        dp[i][j] = true;
                    }else{
                        dp[i][j] = dp[i+1][j-1];
                    }
                }
            }
        }
        for(int i=0;i<s.length();i++){
            for(int j=0;j<s.length();j++){
                if(dp[i][j]){
                    res++;
                }
            }
        }
        return res;
    }

}

2. BufferedRead用法

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.IOException;
//导入的都是java.io的包
public class Main {
//记得抛异常
    public static void main(String[] args) throws IOException {
       	BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        String line = reader.readLine();//读取某一行 为字符串
        writer.write(String X);//输出 必须是字符串形式
        writer.newLine();//换行
        writer.flush();//放在最后,flush()表示强制将缓冲区中的数据发送出去,不必等到缓冲区满.
	}
}

3. 需要定义全局变量

public class Main {
    static int n;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
	}
	private static void test(int m){
		int x = m + n;
	}
}

4. 未知多少行输入

有些输入可能是:
输入一个矩阵,每行以空格分隔。
1 2 3
56 8 2 9
对于这种没有给定矩阵行列数的输入,我们只能按照字符串拆分来进行。
public class test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        List<List<Integer>> list = new ArrayList<>();
        while (sc.hasNextLine()) { //每行都是一个List数组
            List<Integer> line = new ArrayList<>();
            String str = sc.nextLine();
            String[] arr = str.split(" ");
            for (String s : arr) {
                line.add(Integer.valueOf(s));
            }
            list.add(line);
        }
        System.out.println(list); //[[1, 2, 3], [56, 8, 2, 9]]
    }     
}       

典型例子

1. 二叉树:LeetCode删除二叉搜索树的节点(基于Scanner)

/**
 * ACM模式:二叉树 删除搜索二叉树的节点
 * 输入:
 * 5 3 6 2 4 null 7
 * 3
 * 输出:
 * [5,4,6,2,null,null,7]
 * 5 4 6 2 null null 7
 */
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Solution7 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        int key = sc.nextInt();
        String[] parts = line.split(" ");//字符串变数组
        int len = parts.length;
        TreeNode root = strToTree(parts);//数组变树
        TreeNode res = deleteNode(root,key);//题目的处理逻辑
        //树变数组
        Integer[] nums = new Integer[len];
        treeToArray(nums,res,0);
//        //输出1:[5,4,6,2,null,null,7]
//        System.out.println(Arrays.toString(nums));
        String str = Arrays.toString(nums);
        str = str.substring(1,str.length()-1);
        System.out.println(str.replace(","," "));
    }
    private static class TreeNode{
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(){}
        TreeNode(int val){this.val=val;}
        TreeNode(int val,TreeNode left,TreeNode right){
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    private static TreeNode strToTree(String[] parts){

        TreeNode root = new TreeNode(Integer.parseInt(parts[0]));
        int index = 1;
        Queue<TreeNode> que = new LinkedList<>();
        que.offer(root);
        while(!que.isEmpty()){
            TreeNode node = que.poll();
            if(index == parts.length) break;
            String item = parts[index];
            index++;
            if(!item.equals("null")){
                TreeNode left = new TreeNode(Integer.parseInt(item));
                node.left = left;
                que.offer(left);
            }
            if(index == parts.length) break;
            item = parts[index];
            index++;
            if(!item.equals("null")){
                TreeNode right = new TreeNode(Integer.parseInt(item));
                node.right = right;
                que.offer(right);
            }
        }
        return root;
    }
    //树转数组
    private static void treeToArray(Integer[] arr,TreeNode node,int index){
        if(node==null){
            return;
        }
        arr[index] = node.val;
        treeToArray(arr,node.left,2*index+1);
        treeToArray(arr,node.right,index*2+2);
    }

    //处理逻辑
    private static TreeNode deleteNode(TreeNode root,int key){
        if(root == null){
            return null;
        }
        //找到了节点
        if(root.val == key){
            //左右都为空
            if(root.left == null && root.right == null){
                return null;
            }
            //左为空
            if(root.left == null && root.right != null){
                return root.right;
            }
            //右为空
            if(root.left != null && root.right == null){
                return root.left;
            }
            //左右非空,把左孩子移到右孩子最左的孩子
            if(root.left != null && root.right != null){
                TreeNode node = root.right;
                while(node.left!=null){
                    node = node.left;
                }
                node.left = root.left;
                return root.right;
            }
        }
        //没找到
        if(root.val>key){
            root.left = deleteNode(root.left,key);
        }else{
            root.right =  deleteNode(root.right,key);
        }
        return root;
    }
}

2. 链表(基于Scanner)

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

/**
 *  ACM模式:链表  删除链表的倒数第N个结点
 *  输入:
 *      2
 *      [1,2,3,4,5]
 * 输出
 *      [1,2,3,5]
 */
public class Solution8 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int index = sc.nextInt();
        sc.nextLine();
        String line = sc.nextLine();
        ListNode head = strToListnode(line);//字符串变成链表
        ListNode res = removeNthFromEnd(head,index);//处理逻辑
        ArrayList arr = listnodeToArr(res);
        System.out.println(arr.toString());
    }
    //构造链表节点类
    private static class ListNode{
        int val;
        ListNode next;
        ListNode(){}
        ListNode(int val){
            this.val = val;
        }
        ListNode(int val,ListNode next){
            this.val = val;
            this.next = next;
        }
    }
    //字符串变链表
    private static ListNode strToListnode(String line){
        String[] parts = line.substring(1,line.length()-1).split(",");
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        for (String part : parts) {
            cur.next = new ListNode(Integer.parseInt(part));
            cur = cur.next;
        }
        return dummy.next;
    }
    //链表变数组
    private static ArrayList listnodeToArr(ListNode head){
        ArrayList arr = new ArrayList();
        ListNode dummy = new ListNode(-1);
        dummy = head;
        while(dummy!=null){
            arr.add(dummy.val);
            dummy = dummy.next;
        }
        return arr;
    }
    //处理逻辑
    private static ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode slow = dummyNode;
        ListNode fast = dummyNode;
        //设slow走的路程是x,fast是y,画图有y-x=n+1,即fast比slow多走n+1
        for(int i = 0;i<n+1;i++){
            fast = fast.next;
        }
        while(fast!=null){
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dummyNode.next;
    }

}

3. Scanner超时,使用BufferedRead

ACM模式刷题(Java)_第1张图片

//本题逻辑很简单,但是由于有时间要求,如果用普通的for遍历来实现,会导致超时,用sout的方式的会造成时间增加,
//所以需要用BufferedReader和BufferedWriter来进行读写操作
public class Test03 {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        int T = Integer.parseInt(reader.readLine());
        for (int i0 = 0; i0 < T; i0++) {
            int N = Integer.parseInt(reader.readLine());
            char[] a = reader.readLine().toCharArray();
            int M = Integer.parseInt(reader.readLine());
            char[] b = reader.readLine().toCharArray();
            //创建一个对象为优先队列的集合,集合0是0人桌队列,集合1是1人桌队列
            //优先队列数据结构为二叉堆(默认小顶堆,大顶堆需要添加逆序比较器Collections.reverseOrder)
            List<PriorityQueue<Integer>> queueList = new ArrayList<>();
            queueList.add(new PriorityQueue<>());
            queueList.add(new PriorityQueue<>());
            for (int i = 0; i < N; i++) {
                if (a[i] - '0' < 2) {
                    //不同人桌的队列里放从小到大的桌号
                    queueList.get(a[i] - '0').offer(i + 1);
                }
            }
            int x;
            for (int i = 0; i < M; i++) {
                if (b[i] == 'M') {
                    //找1人桌的桌子,假如不为空
                    if (!queueList.get(1).isEmpty()) {
                        //找到1人桌的桌子,输出桌号并出堆
                        x = queueList.get(1).poll();
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    } else {
                        //找到0人桌的桌子,输出桌号并出堆
                        x = queueList.get(0).poll();
                        //将出堆的0人桌插入到1人桌的队列
                        queueList.get(1).offer(x);
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    }

                } else {
                    if (!queueList.get(0).isEmpty()) {
                        x = queueList.get(0).poll();
                        queueList.get(1).offer(x);
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    } else {
                        x = queueList.get(1).poll();
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    }
                }

            }
            writer.flush();
        }
    }
}

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