【Zhejiang University PATest】02-1. Reversing Linked List
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 (<= 105) 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
【solution】
初看题意,很简明易懂。(不要被表象迷惑了。。
链表嘛,还手动给出了节点地址,于是开始写。
等我经历了一番折腾之后,我觉得这道题堪称打表神题,因为它实在是把这个点用表象隐藏得很好。想明白了之后实现就并不难了。 说下我的“心路历程”:
很快发现这题的关键在于“段与段”之间的“地址”连接处要处理好。
一开始,特意用结构体来构造出节点,三个成员,data, addr(自己的地址),next(下一个节点地址),其中地址用字符串来存储,然后创造一个元素是结构体的数组(得强调一下物理地址是相邻的一块内存)。
很自然的,我开始用输入数据构造一个串。怎么构造呢?地址都是字符串,又很自然的,随手开始暴力查找下一个节点,显然是个O(n^2)的。然后想,我擦,不会过不了吧。有优化吗?一时并没有想到(与字符串存地址的先入思维有关)。
然后想,唉这才第二周第一道题,测试数据应该不会很坑吧。(事实上我已经掉坑里了 T_T) 然后写完一测试,一个点超时,一个点竟然还WA了!超时还可以理解,竟然还有WA!
然后首先开始解决WA的问题(因为超时可能也是程序对某些测例出错引起的)。再看代码,边界情况应该都没有问题啊。
在讨论区受陈越姥姥提醒,输入数据中的节点竟然有可能不在有效的需要输出的链上!也就是最后输出的链长可能没有 n !因为输入里面有无效节点!T_T
姥姥(出题人)真是心思缜密啊![苦笑] 然后WA解决了,可是还是有超时。
看来问题是出在 O(n^2) 的构造链上。
再看代码,觉得可能是地址复制来复制去的字符串操作影响了效率,这才终于开始思考把地址用整型来存储。
马上把地址改成了整型,还是超时。
问姥姥,姥姥说是有点小技巧,复杂度是 O(n) 的。
竟然是 O(n) 的!!我才开始认真思考起优化来。
是不是要排序啊?给地址排个序然后二分查找?即便如此也是 O(nlogn) 啊。而且第二周诶,还没讲诶,不会这么复杂吧。[再次苦笑]
开始还一直桎梏于地址为字符串的思路里,甚至想到了 哈希表、优先级队列、完全二叉堆 等等数据结构。可是这才第二周啊![大声苦笑加自嘲]
大概是习惯了打表对于大多数题肯定不会是标准解法(其原因在于题目数据范围一般较大),慢慢的忘了“初心”了。[骗分导论加苦笑!]
这道题真的隐藏得很好,姥姥真是有心了。 思维经历一番千回百转的浪潮,终于想到了将地址作为数组的数值下标,而数组值是数据内容以及下一个节点地址这种被我称作“打表”的办法。
不禁一阵唏嘘啊 T_T 有几点要说:
1、不要小看任何一道题;
2、这道题真正巧妙的揭示了列表和向量的区别与本质,看似题目是列表,实际做起来却是向量(利用向量键值对O(1)的查找,也就是所谓的打表。。);
3、代码中,输出前导0的格式控制:%05d。向右对齐,最少占5位,不足用0填补。要注意最后一个 -1 需要特殊判断(否则输出 -0001 )。 AC代码如下,可能空间上还可以优化,由于我为了尽可能少改动原始版的代码就不做大幅改动了:
#include <stdio.h>
#include <malloc.h> #define AddrMAX 1000004 typedef struct AnsNode
{
int addr, data;
}anode, *panode; int main(void)
{
int n, k, i, j, block, rest, top = ;
int start, temp; scanf("%d %d %d", &start, &n, &k); int* data = (int *)malloc(sizeof(int)*(AddrMAX));
int* next = (int *)malloc(sizeof(int)*(AddrMAX)); panode ans = (panode)malloc(sizeof(anode)*(n+)); for (i = ; i < n; i++)
{
scanf("%d", &temp);
scanf("%d %d", &data[temp], &next[temp]);
} // 按地址将链构造好放入ans中
while (start != -)
{
ans[top].data = data[start];
ans[top].addr = start;
start = next[start];
top++;
}
n = top; // 每 K 段输出一次,并且处理最后一次不足k个的情况,关键点在于“段与段”之间“地址 ”的拼接
block = n / k; rest = n % k;
for (j = ; j < block; j++)
{
for (i = (j + )*k - ; i > j*k; i--)
{
printf("%05d %d %05d\n", ans[i].addr, ans[i].data, ans[i-].addr);
}
printf("%05d %d ", ans[i].addr, ans[i].data);
if (rest == )
{
if (j == block - ) printf("-1");
else printf("%05d", ans[(j+)*k-].addr);
} else
{
if (j == block - ) printf("%05d", ans[(j+)*k].addr);
else printf("%05d", ans[(j+)*k-].addr);
}
printf("\n");
}
if (rest != )
{
for (i = block*k; i < n - ; i++) printf("%05d %d %05d\n", ans[i].addr, ans[i].data, ans[i+].addr);
printf("%05d %d -1\n", ans[i].addr, ans[i].data);
} return ;
}
【Zhejiang University PATest】02-1. Reversing Linked List的更多相关文章
- 【Zhejiang University PATest】02-3. 求前缀表达式的值
算术表达式有前缀表示法.中缀表示法和后缀表示法等形式.前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4.请设计程序计算 ...
- 【Linux常用工具】02. 创建启动定时任务工具cron
一. cron 1. cron是一个守护程序,它提供定时器的功能,让用户在特定的时间得以执行默认的指令或程序.只要用户会编辑定时器的设置文件,就可以使用定时器的功能. 定时器文件格式: 2. cron ...
- 【一起学OpenFoam】02 软件准备
"工欲善其事必先利其器",在利用OpenFoam解决我们的工程问题之前,首先要做的事情是搭建一个OpenFoam运行环境.很遗憾的是,OpenFoam的原生开发系统是Linux,因 ...
- 【C#进阶系列】02 PE文件,程序集,托管模块,元数据——还是那个Hello world
好了,还是这张图,还是一样的Hello world. 因为本章其实很多都是讲一些命令行编译啊什么鬼的配置类的东西,要用的时候直接百度或者回头查书就可以了, 所以了解一下也就行了,也没有记录下来,接下来 ...
- 【AngularJS学习笔记】02 小杂烩及学习总结
表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> < ...
- 【Bootstrap基础学习】02 Bootstrap的布局组件应用示例
字体图标的应用示例 <button type="button" class="btn btn-default"> <span class=&q ...
- 【jQuery基础学习】02 jQuery的DOM操作
DOM操作分为3个方面: DOM Core 任何一种支持DOM Core的语言都可以使用它,比如getElementById就是DOM Core操作 HTML-DOM 只能用来处理web文档 ...
- 【JS复习笔记】02 对象与函数
好吧,因为很重要的事情,几天没写笔记了. 关于对象: ||可以用来填充默认值,如:myApp.name || "无" &&可以用来避免错误,myApp.NameOb ...
- 【C语言学习】-02 分支结构
本文目录: 一.BOOL布尔类型 二.关系运算符 三.逻辑运算符 四.if语句 五.枚举类型 六.switch语句 一.BOOL布尔类型 BOOL数据类型,是一种表示非真即假的数据类型,布尔类型的变量 ...
随机推荐
- Compound Interest Calculator2.0
Compound Interest Calculator2.0 1.如果按照单利计算,本息又是多少呢? 2.假如30年之后要筹措到300万元的养老金,平均的年回报率是3%,那么,现在必须投入的本金是多 ...
- Runner之记计账项目的典型用户分析
- offsetLeft,Left,clientLeft的区别
offsetLeft,Left,clientLeft的区别 假设 obj 为某个 HTML 控件. obj.offsetTop 指 obj 相对于版面或由 offsetParent 属性指定的父坐标的 ...
- Nginx 引入线程池,提升 9 倍性能
转载:http://blog.csdn.net/wuliusir/article/details/50760357 众所周知,NGINX 采用异步.事件驱动的方式处理连接.意味着无需对每个请求创建专门 ...
- linux在shell date获取时间的相关操作
获得当天的日期 date +%Y-%m-%d 输出: 2011-07-28 将当前日期赋值给DATE变量DATE=$(date +%Y%m%d) 有时候我们需要使用今天之前或者往后的日期,这时可以使用 ...
- CSS3学习教程:Media Queries详解
说起CSS3的新特性,就不得不提到 Media Queries . Media Queries 的引入,其作用就是允许添加表达式用以确定媒体的情况,以此来应用不同的样式表.换句话说,其允许我们在不改变 ...
- PHP Memcached应用实现代码
一.memcached 简介 在很多场合,我们都会听到 memcached 这个名字,但很多同学只是听过,并没有用过或实际了解过,只知道它是一个很不错的东东.这里简单介绍一下,memcached 是高 ...
- 微信支付官方SDK V3 .NET版的坑
但是支付成功后却不能正确的执行支付结果js回调函数.看看其页面的点击事件是放在asp:Button上面的.我们知道在asp.net webform中,按钮的点击是有页面回调后台的.也就是其实点击了之后 ...
- 电Call记录统计查询sql
DECLARE @startTime datetimeset @startTime='2016-07-12' SELECT * FROM (--坐席号/电话个数/通话总时长select zuoxi a ...
- JQuery 来获取数据c#中的JSON数据
C# 后台 (JSONHandler.ashx) <%@ WebHandler Language="C#" Class="JSONHandler" %&g ...