按每单元 k 个结点来反转链表。
如,链表为1 -> 2 -> 3 -> 4 -> 5 -> 6,并且k = 4时
结果应为4 -> 3 -> 2 -> 1 -> 5 -> 6
1. 注意到,最后除不尽的那个单元是不翻转的。一开始题目没认真读,囧。
2. 测试点6考察的是输入的结点有的不在链表上的结果。我用dfs做时,就需要重新计算结点总数来限制搜索的深度。
#include <cstdio> #include <vector> #include <iostream> #include <cmath> using namespace std; struct Node { Node() {} Node(int data, int next): m_data(data), m_next(next) {} int m_data; int m_next; }; Node node[100010]; int head, n, k; int add, data, nexx, now; int dfs(const vector<int>& vt, int level) { if (level == 0) { head = vt.back(); } vector<int> new_vt; if (level < n/k -1) { int now = node[vt.back()].m_next; for (int i = 0; i < k; ++ i) { new_vt.push_back( now ); now = node[now].m_next; } } int end = node[vt[k-1]].m_next; for (int i = k-1; i > 0; -- i) { node[vt[i]].m_next = vt[i-1]; } if (level < n/k - 1) { node[vt[0]].m_next = dfs(new_vt, level+1); } else { node[vt[0]].m_next = end; // 此时end == 后面的链表头 或 -1 } return vt.back(); } int count_n() { int cnt = 0; now = head; while (now != -1) { ++ cnt; now = node[now].m_next; } return cnt; } int main() { scanf("%d%d%d", &head, &n, &k); for (int i = 0; i < n; ++ i) { scanf("%d%d%d", &add, &data, &nexx); node[add].m_data = data; node[add].m_next = nexx; } n = count_n(); if (n == 0) { return 0; } vector<int> vt; now = head; for (int i = 0; i < k; ++ i) { vt.push_back(now); now = node[now].m_next; } dfs(vt, 0); now = head; while (node[now].m_next != -1) { printf("%05d %d %05d\n", now, node[now].m_data, node[now].m_next); now = node[now].m_next; } printf("%05d %d %d\n", now, node[now].m_data, node[now].m_next); return 0; }
这份代码比我的短。