计挑-国赛-Java-题5

测试用例1:
5
P1->P3
P2->P4
P4->P1
P3->P5
P1
输出1:
P2
3

测试用例2:
8
P3->P5
P5->P2
P4->P3
P2->P6
P1->P7
P6->P8
P8->P1
P6
输出2:
P4
5

没做出来,但是事后慢慢做出来了,所以是不熟练

很明显这是一个复合数据结构结构的设计题目

样子很像是组合出一条链表,但是涉及到几个问题:

  1. 拼接链表节点的时候,查找链表节点的问题,需要知道节点是否已经存在,存在了还要能获取到才能接
  2. 链表序列的排序问题,拼接过程中每个节点的索引号都是随时变化的,而且链表本身也不支持索引号访问以及根据节点查找索引
    那么
  3. 首先至少要有一个索引map,给每个节点新增一个索引号属性并维护,同时能够根据给出的字段名获取,那毫无疑问肯定是map合适
  4. 其次光能够获取索引号还不够,还要保存并获取节点本身,所以再来一个map

题外话,我觉得这里两个map可能是冗余了,但是按照目前的思路是必要的,除非换个思路

最后是打印头节点,我觉得我这里的处理并不优雅,遍历索引map找索引号为1

一开始是打算用一个变量维护头节点的,但是发现这样做似乎并不能保证正确性

以下是本人代码,复合了两个map和单向链表:

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
    /**
     * key是字符,value是索引位置,主要用来排序,用来给链表排序并查询每个节点的排序位置
     */
    private static final Map<String, Integer> findNodeIndexMap = new HashMap<>();
    /**
     * key是字符,value是节点,用来方便获取节点,因为链表每次获取节点都需要遍历
     * 用来检查节点是否存在
     */
    private static final Map<String, Node> findNodeMap = new HashMap<>();

    /**
     * 链表节点定义
     */
    static class Node {
        Node next = null;
        String name;
        public Node(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine();// 吞掉一行空行
        for (int i = 0; i < n - 1; i++) {
            String str = sc.nextLine();
            String pre = str.substring(0, 2);
            String next = str.substring(4);

            if (findNodeMap.get(pre) == null) {
                /*
                后节点空不空都要新建一个前节点
                 */
                Node newPreNode = new Node(pre);
                findNodeMap.put(pre,newPreNode);
                findNodeIndexMap.put(pre,1);
                if (findNodeMap.get(next) == null) {
                    /*
                    如果两个节点都不存在,就新建这两个节点并加入到map中
                     */
                    Node nodeNext = new Node(next);
                    newPreNode.next = nodeNext;
                    findNodeIndexMap.put(nodeNext.name, 2);
                    findNodeMap.put(nodeNext.name, nodeNext);
                } else {
                    /*
                    前节点空但是后节点不空,就要在前面追加一个新节点
                     */
                    newPreNode.next = findNodeMap.get(next);
                    addIndex(newPreNode);
                }
            } else {
                /*
                前节点存在,修改后节点指针,不存在就new一个
                 */
                Node node = findNodeMap.get(pre);
                Node nextNode;
                if (findNodeIndexMap.get(next) != null)
                    nextNode = findNodeMap.get(next);
                else {
                    nextNode = new Node(next);
                    findNodeMap.put(next, nextNode);
                    findNodeIndexMap.put(next, 1);
                }
                node.next = nextNode;
                addIndex(node);
            }
        }
        // 遍历map找到索引为1的头节点
        findNodeIndexMap.forEach((k,v)-> {
            if(v==1) System.out.println(k);
        });
        /*
        查找指定节点的索引号
         */
        String get = sc.nextLine();
        System.out.println(findNodeIndexMap.get(get));
    }

    /**
     * 追加更新node后面所有的节点索引
     */
    private static void addIndex(Node node) {
        int startIndex = findNodeIndexMap.get(node.name);
        while (node.next != null) {
            node = node.next;// 更新链表节点指针
            findNodeIndexMap.put(node.name, ++startIndex);// 更新节点的索引号
        }
    }
}
posted @ 2022-12-31 17:39  YaosGHC  阅读(39)  评论(0)    收藏  举报