探索通义灵码在算法生成中的无限潜力——链表篇

简介: 书接上文(https://developer.aliyun.com/article/1368451?spm=a2c6h.13148508.setting.14.5a814f0erE5E3T),由于算法的分类较多且实现语言不唯一,故此处想单独另开一文来进行测试。

前言

实测通义灵码:解锁智能编程的钥匙:https://developer.aliyun.com/article/1367211?spm=a2c6h.13148508.setting.15.5f074f0etrEHdr

探索通义灵码在算法生成中的无限潜力——数组篇:https://developer.aliyun.com/article/1367500?spm=a2c6h.13148508.setting.14.5f074f0etrEHdr

探索通义灵码在算法生成中的无限潜力——字符串篇:https://developer.aliyun.com/article/1368451?spm=a2c6h.13148508.setting.14.5a814f0eodKUMp

链表

链表(Linked List)是最简单的线性的、动态数据结构。理解它是理解树结构、图结构的基础。

区别于数组,链表中的元素不是存储在内存中连续的一片区域,链表中的数据存储在每一个称之为「结点」复合区域里,在每一个结点除了存储数据以外,还保存了到下一个节点的指针(Pointer)。

image.png

由于不必按顺序存储,链表在插入数据的时候可以达到 O(1) 的复杂度,但是查找一个节点或者访问特定编号的节点则需要 O(n) 的时间。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接(links)。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的访问往往要在不同的排列顺序中转换。而链表是一种自我指示数据类型,因为它包含指向另一个相同类型的数据的指针(链接)。

链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。

链表通常可以衍生出循环链表,静态链表,双链表等。对于链表使用,灵活使用虚拟头结点可以简化问题。

删除链表中的节点

image.png

给出提问如下:

有一个单链表的 head,我们想删除它其中的一个节点 node。
给你一个需要删除的节点 node 。你将 无法访问 第一个节点 head。
链表的所有值都是 唯一的,并且保证给定的节点 node 不是链表中的最后一个节点。
删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:
给定节点的值不应该存在于链表中。
链表中的节点数应该减少 1。
node 前面的所有值顺序相同。
node 后面的所有值顺序相同。
请根据下述代码完成:
class Solution:
def deleteNode(self, node):

生成代码如下:

image.png

对照之后存在错误,根据报错信息,'ListNode' object has no attribute 'head',可以推测出ListNode类中没有定义head属性或方法。

image.png

于是开启我的调教大法,告知它存在这个问题,让它优化完善。

image.png

但是不巧的是,仍然存在报错,经过多次尝试后,发现均有不同程度报错,且即使多次调教和定向训练后仍然存在不同程度语法错误

最后还是决定利用大模型的随机性,在经过 9clear context(清楚记忆重新生成),终于给我生成出了一次正确答案。

image.png

给出代码及对照结果, 正确

image.png

但由于前两篇的经验,此处我开始尝试让通义灵码在保证正确性的前提下降低时间、空间复杂度

image.png

果真有用!

image.png

删除链表的倒数第N个节点

image.png

给出提问如下:

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。请结合以下代码来完成:
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:

生成代码如下:

image.png

但是奇怪的是,此次代码结果竟然又是存在语法错误的!经过一些排查,其实我发现该代码逻辑似乎并无问题,只是通义灵码语义理解时出现了偏差

根据题设是给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。(下方红框所示)

image.png

但是根据通义灵码的理解意思,它理解的头结点是链表的第一位。

image.png

此处也可以通过通义灵码自身的解释看出:

image.png

随后,我告知了它正确的示例:

image.png

给出代码及对照结果, 正确

image.png

反转链表

image.png

给出提问如下:

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。请根据下述代码来完成:
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:

生成代码如下:

image.png

给出代码及对照结果, 正确 ,今天难得的一遍过!

image.png

时间、空间复杂度都比较可观了。

合并两个有序链表

给出提问如下:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 请根据下述代码完善:class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:

生成代码如下:

image.png

【解释】:

  1. 首先判断两个链表是否为空,如果有一个为空,则返回非空的链表。

  2. 创建一个虚拟节点dummy和当前节点curr,用于拼接两个链表的结果。

  3. 使用循环遍历两个链表,每次比较两个链表当前位置节点的值,将较小的值拼接到新链表上,并将指针后移。

  4. 遍历完两个链表后,若某个链表还未遍历完,则将其剩余部分接在新链表的尾部。

  5. 返回虚拟节点dummy的下一个节点作为新链表的头节点。

给出代码及对照结果, 正确

image.png

看起来时间复杂度有些高了,于是我试着告诉它:

image.png

于是乎:

image.png

回文链表

image.png

给出提问如下:

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。请结合下述代码来完成:class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:

生成代码如下:

image.png

给出代码及对照结果, 正确

image.png

时间、空间复杂度依旧很可观!

环形链表

image.png

给出提问如下:

给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。请结合下述代码完成:class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:

生成代码如下:

image.png

给出代码及对照结果, 正确

image.png

继续降低时间、空间复杂度。

image.png

效果太显著了!

image.png

结论

总体来看,通义灵码对于基础链表的处理还是很好的,但是根据今天的测试内容来看有两点是跟前几次不一样的:

  1. 在处理链表类型题目时较容易出现语法错误。比如常见的:缩进错误、缺少定义属性或方法等。(这两个较为常见)

  2. 对于链表代码问题的引导调优有些困难,说白了就是此时通义灵码似乎特别“固执”,尤其是语法问题的优化有些死板。


题目 最初答案 最终答案 执行用时 内存消耗
删除链表中的节点 × 超过75.88% 超过92.07%
删除链表的倒数第N个节点 × 超过40.86% 超过75.04%
反转链表 超过76.14% 超过99.42%
合并两个有序链表 超过97.74% 超过40.70%
回文链表 超过87.80% 超过72.56%
环形链表 超过53.65% 超过99.18%

【注意】最初答案指第一次生成的答案是否正确;最终答案指多次调教之后生成的答案是否正确;执行用时越,超过的比例就越多;内存消耗越,超过的比例就越多。

相关文章
|
3月前
|
存储 算法 C语言
【数据结构与算法 刷题系列】合并两个有序链表
【数据结构与算法 刷题系列】合并两个有序链表
|
1月前
|
算法
【算法】合并两个有序链表(easy)——递归算法
【算法】合并两个有序链表(easy)——递归算法
【算法】合并两个有序链表(easy)——递归算法
|
1月前
|
存储 算法
【初阶数据结构篇】顺序表和链表算法题
此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。
|
1月前
|
算法
【数据结构与算法】共享双向链表
【数据结构与算法】共享双向链表
11 0
|
1月前
|
算法
【数据结构与算法】双向链表
【数据结构与算法】双向链表
10 0
|
1月前
|
算法
【数据结构与算法】循环链表
【数据结构与算法】循环链表
12 0
|
1月前
|
存储 算法
【数据结构与算法】链表
【数据结构与算法】链表
16 0
|
1月前
|
算法
【C算法】链表算法
【C算法】链表算法
|
1月前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
43 0
|
1月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
18 0