对于线性表的操做过程有有多问题能够探究,在不少的题目里有的甚至会对操做的时间进行规定,这就很是考究算法的效率。根据不一样的状况对排序方法或者是对链表或顺序表的选择,能够节省其运行时间。而算法又是比较有难度的一部分,对初次认识一种算法的人仍需时间去理解,能够说这就是人与计算机不可兼得的一方面。
对于链表的操做,时刻都要考虑指向非法区域的状况,这也是我常常不自觉要忽略的一点。python
设计函数分别求两个一元多项式的乘积与和。
输入格式:程序员
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:算法
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。
对于这道题目我尝试了两种解决方法:数组
这种方法对时间和空间的消耗都是魔鬼,可是对程序员倒是十分友好,这也是我一开始使用这种方法的缘由。
简而言之,十分暴力。
设计思想:构造一个尽可能大的数据,而且使用static使得全部初值均为0,这样就能判断每一项是否是存在。而后将加法和乘法的每一项结果都存进以指数为下标的数组里。要输出的时候就遍历所有数组,非0就输出。很暴力呢函数
!--如下伪代码都将采用python缩进表示语句块的方法--<学习
定义存储多项式的数组a[MAX],b[MAX] 以及用来存储的数组plus[MAX],Mult[MAX] //对于全部数组都用静态,这样他们就都是0了,方便判断是否为空 //还有就是数组下标就表明有几回方,其内容就是系数 //下面开始对结果计算的操做: //乘法: for i = 0 to MAX-1: if a[i]: for j = 0 to MAX-1: if b[i]: Mult[i + j] += a[i] * b[j] //系数相乘,指数相加 //加法 for i = 0 to MAX-1 if a[i] or b[j]: plus[i] += (a[i] + b[i]) //如上便完成了操做过程
//代码这东西,不是电脑难受,就是我难受(小声嘀咕)
设计思想:初始化一个新元素elem,而后一样地将每次计算加法或者乘法的结果存入elem,再利用一个Insert函数将elem插入到结果链表中。动画
//先丢出结构体 typedef struct LNode { int coe; int index; LNode * next; }*LinkList; //常规的建表输出表就不贴啦 //我先设计了两个初级函数,用于计算每一项的结果,并调用Insert函数插入结果链表中: void Multply(LinkList L1, LinkList L2, LinkList result) LinkList p = L1, q while p->next://遍历 初始化q为L2 while q->next://遍历 为elem分配空间,而后将p,q节点的计算结果存储到elem if elem->coe == 0: elem->index = 0 p = p->next void Add(LinkList L1, LinkList L2, LinkList result) //Add函数也比较简单,把每一个链表的节点丢给Insert函数就好啦 //这两个函数的大体功能相似,只不过是一个节点中转站 //接下来是Insert函数,其大体思想就是利用输入数据的指数递减的特色,尝试查找比elem指数小的节点 void Insert(LinkList elem, LinkList &result) while p->next: if p->next->index == elem->index://说明找到 将elem的系数与当前p->next相加 delete elem return; //return 很重要 else if p->next->index < elem->index://找过头了仍是没有找到 将elem插入在当前p->next的前面 return; p = p->next //通过上述循环仍没找到说明应该插在末尾 插在末尾
数组实现:
网站
链表实现:
设计
WA1:忘记考虑系数为0时指数不为0的状况
Solution:在Insert以前加个if语句判断就行了3d
WA2:我觉得题目的“0 0”状况是有系数为0的就用合并输出。。
Solution:去和以前写的数组法对比了一下差异,再回过头来看看题目才发现
已知两个递增链表序列L1与L2,2个链表都是带头结点链表。设计函数实现L1,L2的合并,合并的链表仍然递增有序,头结点为L1的头结点。 合并后须要去除重复元素。 * 输入格式: 输入分两行,先输入数据项个数,再输入数据项,数字用空格间隔。 * 输出格式: 在一行中输出合并后新的递增链表,数字间用空格分开,结尾不能有多余空格;
你须要实现的函数为:
void MergeList(LinkList &L1,LinkList L2);//合并链表
这题不算难,可是手上有一个有趣的解法就拿出来分享一下,其大体原理如图
设计思想:比较L1和L2头元素的大小,将二者之中最小的元素拆下来使用尾插法插入结果链表,而且让拆过的链表头指向下一节点。
void MergeList(LinkList &L1, LinkList L2) 新建一个结果链表L3 head = L3 while L1 or L2: if L1->data == head->data: L1=L1->next else if L2同上: else: 使head->next指向L1, L2中的最小值节点 并使该节点指向它的下一个 head->next = NULL L1 = L3
WA1:写这题时也不知怎么了,感受脑子忽然不在线了,出现不少低级错误,好比定义告终果链表L3,可是都没用过就给人家L1=L3,太智障了我。。
Solution:让脑子冷静一下。。。
WA2:发现有的重复数据仍是没有过滤掉
Solution:设置断点调试,最后发现是只考虑了L1,L2有共同元素却没有考虑单个链表中重复的状况。
本题要求实现一个函数,将给定单向链表逆置,即表头置为表尾,表尾置为表头。链表为带头结点链表。请实现逆转函数。
输入说明:
第一个数输入单链表结点个数n,后面输入n个正整数。
输出说明:
输出逆转后的单链表内容,数和数之间空格隔开,尾部不能有空格。若链表为空,输出 空链表!
设计思想:感受就像桥梁施工队同样,为了防止后面的桥梁坍塌,必须把后面的吊住,这就是操做变量after的功能,利用before和p实现两个节点之间的逆转,原先是before下一个指向p,修改为p下一个指向before。
void ReverseList(LinkList &L) p = L->next; 定义操做变量before = NULL,after while p: //移动after的位置 after = p->next //先改变p的指向 p->next 移动before和p L->next = before
这个感受实在是太抽象了,伪代码不太好表达,因此用PPT作了个动画,应该会比较好懂
元素解释:红色表明操做变量,黄色表明链表的每个节点,蓝色表明指针指向
WA1:多是太累了,一直没给L头节点,而后输出函数也是写的没头节点,一直在纳闷。
Solution:经历太多失败恍然大悟
给定一个链表,判断链表中是否有环。 为了表示给定链表中的环,咱们使用整数 pos 来表示链表尾链接到链表中的位置(索引从 0 开始)。 若是 pos 是 -1,则在该链表中没有环。
多种思路:
(这里就直接照搬题解了)
思路想象一下,两名运动员以不一样的速度在环形赛道上跑步会发生什么?
经过使用具备 不一样速度 的快、慢两个指针遍历链表,空间复杂度能够被下降至 O(1)O(1)O(1)。慢指针每次移动一步,而快指针每次移动两步。
若是列表中不存在环,最终快指针将会最早到达尾部,此时咱们能够返回 false。
这种解法会破坏链表,大体思路就是每走一步就而后让每一个节点本身指本身,这样若是存在环势必会遇到一个自攻自受的节点,这就是答案了
1.快慢指针法
2.无限循环法
感受常常逛一逛这些网站仍是挺有意思的,能看见各类不一样的奇葩思路,也很是适合用来对新学习的语言进行练手,由于它支持不少种编译器,牛逼