141.环形链表
访问次数比较,想到用哈希表,但是不知道ListNode*的数据类型能不能用。事实是可以的。
- 哈希表作为一种抽象数据类型,包括数据成员和增删改查操作、哈希、冲突及解决方案(open address)
- 可以作为Key的数据类型是int,float,str,object,不可以的数据类型是bool,list,tuple,dict,set
- 原因是:list,tuple,dict,set是mutable 可修改的,不可以作为key放在dict里
- 哈希函数把hash code(int float str转化为整数)/tabel.size=index
- 自定义的object可以把data member分别变成hashcode(即把int float str bool等值变成hashcode),在这种条件下增删改查的时间复杂度都是O(1)
21.合并两个有序链表
方法一:迭代(自己想到这种算法,但是不知道这就是迭代QWQ)
当 l1 和 l2 都不是空链表时,判断 l1 和 l2 哪一个链表的头节点的值更小,将较小值的节点添加到结果里,当一个节点被添加到结果里之后,将对应链表中的节点向后移一位。
设定一个哨兵节点 prehead
,这可以在最后比较容易地返回合并后的链表。
维护一个 prev
指针,我们需要做的是调整它的 next
指针。
方法二:递归
两个链表头部值较小的一个节点与剩下元素的 merge
操作结果合并。
如果 l1 或者 l2 一开始就是空链表 ,那么没有任何操作需要合并,所以我们只需要返回非空链表。否则,要判断 l1 和 l2 哪一个链表的头节点的值更小,然后递归地决定下一个添加到结果里的节点。如果两个链表有一个为空,递归结束。
头指针:
- 指向第一个结点的指针,若链表有头结点,则头指针就是指向链表头结点指针。
- 头指针有标识作用,常用头指针作为链表的名字。
- 无论链表是否为空,头指针都不为空。头指针是链表的必要元素。
头结点:
- 头结点不是链表必须的,可有可无。
- 首节点就是第一个元素的结点,它是头结点后面的第一个结点。
- 头结点是为了操作统一与方便而设立的,放在第一个元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用作监视哨等等)。
- 有了头结点之后,对在第一个元素结点前插入节点和删除第一个结点,其操作与对其它结点的操作统一了。
203.移除链表元素
方法一:迭代
- 用 temp 表示当前节点。
- 如果 temp 的下一个节点不为空且下一个节点的节点值等于给定的 val,则需要删除下一个节点。如果 temp的下一个节点的节点值不等于给定的 val,则保留下一个节点,将 temp 移动到下一个节点即可。
- 当 temp 的下一个节点为空时,链表遍历结束,此时所有节点值等于 val的节点都被删除。
由于链表的头节点 head 有可能需要被删除,因此创建哑节点 dummyHead,令 dummyHead.next=head,初始化 temp=dummyHead,然后遍历链表进行删除操作。最终返回 dummyHead.next 即为删除操作后的头节点。
方法二:递归(这个递归好难啊qwq)
链表的定义具有递归的性质,因此链表题目常可以用递归的方法求解。
首先对除了头节点 head 以外的节点进行删除操作,然后判断 head的节点值是否等于给定的 val。
如果 head 的节点值等于 val,则 head需要被删除,因此删除操作后的头节点为 head.next;如果 head 的节点值不等于 val,则 head 保留,因此删除操作后的头节点还是 head。
递归的终止条件是 head 为空,此时直接返回 head。当 head 不为空时,递归地进行删除操作,然后判断 head的节点值是否等于 val 并决定是否要删除 head。