Loading

每日力扣2

160. 相交链表

题目:

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

图示两个链表在节点 c1 开始相交**:**

image-20230919215725991

思路:

A链表长度为a+b,B链表长度为c+b,因此让两个指针p1,p2分别从A、B的头开始遍历,当A到结尾时p1指向B的头,B到结尾时p2指向A的头,当他们第一次相等时,要么是都为null,此时说明他们没有节点,要么就都指向了同一个节点,此时p1走了a+b+c的路程,而p2指针也走了a+b+c的路程,肯定是第一个节点。

141. 环形链表

题目:

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。同时求出环的长度,环的入口。

image-20230919215813067

思路:

现假设有环,那么环之前的长度是a,环长是b。建立一个快慢指针f与s,当此时他们一起向后移动,f每次移动2,s每次移动1。由于每次走,f 都会比 s 多走一个距离。而链表是一个环,能一直走下去,因此 f 一定会追上 s 。此时 f=2 s。当他们相遇时,此时f一定是比s多走了 n个环的距离,即 f=s+nb,可以得到 s=nb。即此时s的总距离是n个环长。而在环入口的距离一定是 a+kb,即走了链入口的距离到达入口点,然后再走了k圈环。所以此时 s 再走 a 的距离就到达了入口,而从链表头节点到入口的距离也是a,因此用一个指针p指向头节点,然后让p和s一起向后走,当他们相等时,就说明走到了入口。

如果要求环长度的话,当f、s第一次相遇后,他们再一次相遇就是所走过的距离的差就是环长。因为第一次相遇后f、s位于同一起点,然后f、s 一起走,s 走了一个环长时恰好 f 走了两个环长,此时相减则是环长 b 。

25. K 个一组翻转链表

题目:

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

image-20230919215957191

思路:

先给头节点加上一个虚拟节点,然后做出一个翻转指定长度链表的函数,每k次则调用一次。

l 是翻转的起始节点的前一个节点,r 是翻转结束节点的后一个节点,因此函数的参数是翻转起始节点,l1 ,终止节点是r1,翻转完后,l.next=r1 l1.next = r。然后更新 l 和 r 。

146. LRU 缓存

题目:

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

思路:

在内部用Map维护一个缓存,然后用双向链表去维护一个缓存的值,每次存入一个元素就将该元素注册成链表中的节点,然后放入链表尾部。每次用get方法时也将该节点移入链表尾部。在调用put时先查看放入的key存不存在,如果存在就直接跟新节点,将节点移入尾部;如果不存在则判断元素个数有没有超过限制,超过了则删除链表头节点,根据该节点对应的key去Map中删除k-v对,然后插入新元素,包装成链表节点放入尾部。

链表结构:key,v,next,pre。

在LRU类中维护一个头节点和尾节点。建立链表的尾插入方法,删除头方法,删除指定节点方法,移动到尾部方法。

posted @ 2023-09-27 19:27  墨鱼yyyl  阅读(7)  评论(0)    收藏  举报  来源