Given a constant and a singly linked list , you are supposed to reverse the links of every elements on . For example, given being 1→2→3→4→5→6, if , then you must output 3→2→1→6→5→4; if , 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 which is the total number of nodes, and a positive 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 lines follow, each describes a node in the format:
Address Data Next
where
Address
is the position of the node,Data
is an integer, andNext
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 33218Sample 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.
需要反转的链表长度
- address of the first node
为了避免 对节点按链接顺序排序导致时间复杂度增加
两种解决方式
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了…真的难受