02-线性结构3 Reversing Linked List(25 分)【Java实现超时】

Given a constant K and a singly linked list L , you are supposed to reverse the links of every K elements on L . For example, given L being 1→2→3→4→5→6, if K = 3 , then you must output 3→2→1→6→5→4; if K = 4 , you must output 4→3→2→1→5→6.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N ( 10 5 ) which is the total number of nodes, and a positive K ( N ) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1


思路

  • 输入的第一行
    • address of the first node
      头节点的地址
    • the total number of nodes
      确定读取的循环次数
    • the length of the sublist to be reversed.
      需要反转的链表长度

为了避免 对节点按链接顺序排序导致时间复杂度增加

两种解决方式

1. 空间换时间,用数组,下标表示节点地址

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;

public class Main {
    private static Node[] nodeList = new Node[100000];

    private static class Node {
        int data;
        int next;
    }

    //读入节点
    public static void readNode(BufferedReader br, int cnt) throws IOException {
        for (int i = 0; i < cnt; i++) {//读取各个节点数据
            String[] nodeInfo = br.readLine().split(" ");
            int address = Integer.parseInt(nodeInfo[0]);
            Node node = new Node();
            node.data = Integer.parseInt(nodeInfo[1]);
            node.next = Integer.parseInt(nodeInfo[2]);
            nodeList[address] = node;
        }
    }

    //对地址进行筛选并排序
    public static List<Integer> rankAddr(int headAddr) {
        List<Integer> rankedAddr = new LinkedList<>();
        int address = headAddr;
        while (address != -1) {
            rankedAddr.add(address);
            address = nodeList[address].next;
        }
        return rankedAddr;
    }

    //地址的反转
    public  static List<Integer> reverseAddr(List<Integer> rankedAddr, int k) {
        List<Integer> finalAddr = rankedAddr;

        if (k != 1) {//如果反转的长度不为1,即有反转
            int reverseGroup = finalAddr.size() / k;//需要反转的组数
            int startIndex = 0;
            int endIndex = k - 1;

            while (reverseGroup > 0) {//反转
                for (int i = 0; i < k / 2; i++) {
                    int tempAddr = finalAddr.get(startIndex + i);
                    finalAddr.set(startIndex + i, finalAddr.get(endIndex - i));
                    finalAddr.set(endIndex - i, tempAddr);
                }
                startIndex += k;
                endIndex += k;
                reverseGroup--;
            }
        }
        return finalAddr;
    }

    //输出节点
    public static void printNode(List<Integer> finalAddr) {
        for (int i = 0; i < finalAddr.size(); i++) {
            Integer address = finalAddr.get(i);
            if(i == finalAddr.size() - 1){//最后一个地址
                System.out.printf("%05d %d -1\n", address, nodeList[address].data);
            }else{
                Integer nextAddr = finalAddr.get(i + 1);
                System.out.printf("%05d %d %05d\n", address, nodeList[address].data, nextAddr);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String[] info = br.readLine().split(" ");

        int headAddr = Integer.parseInt(info[0]);//头节点的地址
        int cnt = Integer.parseInt(info[1]);//节点的数量
        int k = Integer.parseInt(info[2]);//要翻转的长度

        readNode(br, cnt);
        br.close();

        List<Integer> rankedAddr = rankAddr(headAddr);
        List<Integer> finalAddr = reverseAddr(rankedAddr, k);
        printNode(finalAddr);
    }
}

2. map通过 键值对,存储 地址 和 节点

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Stack;
import java.util.TreeMap;

public class Main {

    private static Map<String, Node> nodeMap = new TreeMap<>();

    private static class Node{
        String address;
        int data;
        String next;
    }

    public static void readNode(BufferedReader br, int cnt) throws IOException {
        for (int i = 0; i < cnt; i++) {//读取各个节点数据
            String[] nodeInfo = br.readLine().split(" ");
            String address = nodeInfo[0];
            Node node = new Node();
            node.address = address;
            node.data = Integer.parseInt(nodeInfo[1]);
            node.next = nodeInfo[2];
            nodeMap.put(address, node);
        }
    }

    //获取真正节点的数量
    public static int rankAddr(String headAddr) {
        int cntOfNode = 0;
        String address = headAddr;
        while (!address.equals("-1")) {
            address = nodeMap.get(address).next;
            cntOfNode++;
        }
        return cntOfNode;
    }

    //通过栈实现节点排序的反转
    public static void printResult(String headAddr, int cntOfNode, int k){
        String address = headAddr;
        Stack<Node> stack = new Stack<>();
        int cntOfReverse = 0;
        if(k != 1){
            cntOfReverse = cntOfNode - (cntOfNode % k);
        }

        boolean isFirstLine = true;
        /*if(address == "-1"){//如果头节点地址为 -1
            return;
        }*/

        Node currentNode;
        if(cntOfReverse != 0) {//需要反转
            for (int i = 0; i < cntOfReverse; i++) {//需要反转的数量
                currentNode = nodeMap.get(address);
                stack.push(currentNode);
                address = currentNode.next;

                if (i % k == k - 1) {
                    while (!stack.empty()) {
                        currentNode = stack.pop();
                        if (!isFirstLine) {//如果不是第一行
                            System.out.printf("%s\n", currentNode.address);
                        }
                        System.out.printf("%s %d ", currentNode.address, currentNode.data);
                        isFirstLine = false;
                    }
                }
            }
        }

        for(int i = cntOfReverse; i < cntOfNode; i++){//末尾 不在这里输出
            currentNode = nodeMap.get(address);
            if (!isFirstLine) {//如果不是第一行
                System.out.printf("%s\n", currentNode.address);
            }
            System.out.printf("%s %d ", currentNode.address, currentNode.data);
            isFirstLine = false;
            address = currentNode.next;
        }
        System.out.println(address);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String[] info = br.readLine().split(" ");

        String headAddr = info[0];//头节点的地址
        int cnt = Integer.parseInt(info[1]);//节点的数量
        int k = Integer.parseInt(info[2]);//要翻转的长度

        readNode(br, cnt);
        br.close();
        int cntOfNode = rankAddr(headAddr);
        printResult(headAddr, cntOfNode, k);
    }
}

觉悟!!!

这里写图片描述
PAT/PTA的某些算法题目对运行时间的要求,导致同样的方法,用JAVA实现会运行超时。就算写出了解法,对自身也是造成挫败感… 博主正式放弃用Java入门数据结构的学习…先去学C了…真的难受

猜你喜欢

转载自blog.csdn.net/weixin_39345384/article/details/80195978