文章目录
1、反转链表
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
# write code here
if not head:return None
prev=None# 前驱节点
cur=head# 当前节点
while cur:
cur.next,prev,cur=prev,cur,cur.next
# 下一个节点指向了前驱节点,前驱就指向当前的节点(因为要往后做了),当前就也往后挪一个
# 其实说简单一点就是借助节点,其实我们的链表是没有改变的,只是获得链表内容的节点顺序改变了
return prev
上下两个方法是一样的,但是下面那个更绕一点
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
# write code here
# 借助栈 先进后出 一个一个插进去(因该是这样的)
# 有点绕 大概就是弹出一个 然后压入 再弹出一个 再压入
# 设置两个指针,一个当前节点的指针,一个上一个节点的指针(初始为空)
pre = None# 先定义空 前驱节点
while(head):# 这里就是第一个插进去
temp = head.next# 除开第一个
head.next = pre
pre = head
head = temp
return pre
2、链表内指定区间反转
class Solution:
def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
# write code here
if m==n:
return head
if not head and head.next:# head为空且head.next不为空
return head
dummy = ListNode(0)
dummy.next = head# 新建一个链表 头上加了一个数字0
pre = dummy # dummy的指针
cur = head # cur是head的指针
for i in range(m-1):#前面几个直接加里边
pre = cur
cur = cur.next
for i in range(n-m):# 这个就是直接反转链表就行了
temp = cur.next# temp先存一下下一个节点
cur.next = temp.next# cur的下一个就等于temp的下一个 就相当于是cur的下一个
# 当前指向下一个
temp.next = pre.next# temp下面就指向当前
pre.next = temp # 这里的pre就像之前那道题的前驱节点,因为他是多了一个节点的,所以他就是前一个
# 前驱指向当前
return dummy.next
3、链表中的节点每k个一组翻转
这里需要注意一下,如果不足k个是不需要翻转的,所以这里的方法是特别好的。
class Solution:
def reverseKGroup(self , head: ListNode, k: int) -> ListNode:
# write code here
# # 因为这个是链表 所以不能用这个方法
# n=len(head)
# for i in range(n//k):
# k1=i*k
# k2=(i+1)*k
# y=head[k1:k2]
# y=y[::-1]
# head=head[0:k1]+y+head[k2:]
# return head
cur = head# 指针
cnt = 0 #一个参数
while cur and cnt != k:# 这里就是在不断的后移
cur = cur.next
cnt += 1
if cnt == k:
cur = self.reverseKGroup(cur,k)# 指针到k+1个的时候 再调用这个函数
while cnt:# 这里在翻转
head.next,cur,head = cur,head,head.next
cnt -= 1
head = cur # 转换之后 把他赋值给head 我们的cur是不会再回到一的 他是在原始的head里做处理 只改变指针
return head
# 还没看懂
4、合并两个排序的链表
class Solution:
def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
# write code here
dummy=cur=ListNode(-1) #dummy是尾 cur是一个指针 这一步是必要的
while pHead1 and pHead2:# 任意一个不空
if pHead1.val<=pHead2.val:
cur.next=pHead1
pHead1=pHead1.next
else:
cur.next=pHead2
pHead2=pHead2.next
cur=cur.next# 从这往下是欠缺的地方
cur.next=pHead1 if pHead1 else pHead2 # 这里是最后比完了在看没有装进来的东西
return dummy.next
5、合并k个已排序的链表
分治法 简而言之就是
1.只有一个链表时返回该链表
2.只有两个链表时返回合并后的链表
3.有两个以上链表时,拆分成两部分分别合并
下面就是这个方法做的,分成两部分,分别求合并
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:# 合并俩
head = ListNode(None)
p = head
while l1 and l2:
if l1.val <= l2.val:
p.next = l1
l1 = l1.next
else:
p.next = l2
l2 = l2.next
p = p.next
if not l1:
p.next = l2
else:
p.next = l1
return head.next
def mergeKLists(self, lists: List[ListNode]) -> ListNode:# 合并k
n = len(lists)
if n == 0:
return None
return self.mergeLR(lists,0,n-1)
def mergeLR(self,lists,L,R):# 合并k下面的左右平分合并
if R == L:#就是len(list)==1
return lists[L]
if R-L != 1:# 当不是2的时候 就开始平分 若是为2 就直接用合并2
mid = (L+R)//2
lists[L] = self.mergeLR(lists,L,mid)
lists[R] = self.mergeLR(lists,mid+1,R)
return self.mergeTwoLists(lists[L],lists[R])
一个笨方法
简单点来说就是 把所有的链表放一起 然后排序之后再放在一个链表里
class Solution:
def mergeKLists(self , lists: List[ListNode]) -> ListNode:
# write code here
# 这个是把他转换为了一个大的list来做的,下面有个tmp.sort
tmp = []
for node in lists:
while node:
tmp.append(node.val)
node = node.next
if not tmp:
return None
tmp.sort()
cur = head = ListNode(tmp[0])
for i in range(1,len(tmp)):
node = ListNode(tmp[i])
cur.next = node
cur = cur.next
return head
6、判断链表中是否有环
class Solution:
def hasCycle(self , head: ListNode) -> bool:
fast = head
slow = head
while slow!=None and fast.next!=None and fast.next.next!=None:
fast = fast.next.next;
slow = slow.next;
if fast==slow:
return True
return False
7、链表中环的入口结点
class Solution:
def EntryNodeOfLoop(self, pHead):
if not pHead:
return None
slow = fast = pHead
while slow and fast:# 俩都不为空的时候
if not slow.next or not fast.next:# 二者中任意一个的next不为none
return None
slow = slow.next
fast = fast.next.next # 第二个链表
if slow == fast:
while slow != pHead:
pHead = pHead.next
slow = slow.next
return slow
return None
下面是另一个方法,借助了一个新的表来做的
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
addr = []
while pHead.next != None: # 遍历
addr.append(pHead) # 记录地址到列表
pHead = pHead.next # 遍历下一个
if pHead.next in addr: # 存在下一个链表地址在列表中,则下一个链表就是入口
return pHead.next
return None # 无法循环,返回空
8、链表中倒数最后k个结点
和刚刚的环有点类似,借助快指针和慢指针,快指针比满指针先走k步,当快指向none了,慢就可以开始输出了
class Solution:
def FindKthToTail(self , pHead: ListNode, k: int) -> ListNode:
# write code here
# 两个指针隔开k出发 当先出发的到尾巴的时候 后出发的那个就开始返回值就行
fast=slow=pHead
n=0
while pHead:
n+=1
pHead=pHead.next
print(n)
if n<k:
return None
else:
for i in range(k):
fast=fast.next
while fast:
fast=fast.next
slow=slow.next
return slow
9、删除链表的倒数第n个节点
这个方法和上面的一样,他是直接就先把前n个一一存起来,然后删掉第n个,之后再直接加上就行了
class Solution:
def removeNthFromEnd(self , head: ListNode, n: int) -> ListNode:
# write code here
slow=head
fast=head
for _ in range(n):
fast=fast.next
if not fast:
return head.next# 这里就是当fast到最后了 就除掉当前
while fast.next:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return head
10、两个链表的第一个公共结点
class Solution:
def FindFirstCommonNode(self , pHead1 , pHead2 ):
# write code here
# 分别记为x、y、z,1、2、共同,那么让A走xzy b走yzx 那么最后都是指到了z的第一个
pa,pb= pHead1 , pHead2
while pa!=pb:
pa=pa.next if pa else pHead2
pb=pb.next if pb else pHead1
return pa
11、链表相加(一)
这个循环时间会比较长
class Solution:
def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
# write code here
up = 0 #设置进位
head = ListNode(0) #设置表头
node = head #设置中间节点
while l1 or l2:
x = l1.val if l1 else 0 #if else语句是为了防止两个输入链表不一样长导致为None
y = l2.val if l2 else 0
s = x + y + up #求和时要加上进位值
up = s // 10 #和大于10则进位
node.next = ListNode(s % 10) #输出链表增加一个节点
if l1:
l1 = l1.next
if l2:
l2 = l2.next
node = node.next #更新链表的next
if up != 0: #检查最后一位是否进位
node.next = ListNode(1) #进位则加上一个1的节点
return head.next #返回时记得去除表头的0节点,即head本身
这个的时间也会超
class Solution:
def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
# write code here
# 初始化个位节点,先不做进位
newPoint = ListNode(l1.val + l2.val)
# rt用来作为最后return的节点,tp用来遍历节点
rt, tp = newPoint, newPoint
# l1,l2只要后面还有节点,就继续往后遍历;或者新链表还需要继续往后进位
while (l1 and (l1.next != None)) or (l2 and (l2.next != None)) or (tp.val > 9):
l1, l2 = l1.next if l1 else l1, l2.next if l2 else l2
tmpsum = (l1.val if l1 else 0) + (l2.val if l2 else 0)
# 计算新链表下个节点的值(当前节点的进位+当前l1 l2的值之和),先不做进位
tp.next = ListNode(tp.val//10 + tmpsum)
# 新链表当前节点的值取个位
tp.val %= 10
# 新链表往后遍历一个节点
tp = tp.next
return rt
递归
class Solution:
def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
# write code here
# 某一个加数不存在,那么结果即为另一个加数
if l1 is None:
return l2
if l2 is None:
return l1
# 加数都存在,取对位相加,除以10取余
x = l1.val if l1 else 0
y = l2.val if l2 else 0
re = ListNode((x + y) % 10)
# 下一个节点,即为l1和l2下一个节点相加,再加上此节点的进位
re.next = self.ListAdd(l1.next, l2.next)
if x + y > 9:
re.next = self.ListAdd(re.next, ListNode((x + y) // 10))
return re
循环
class Solution:
def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
# write code here
#########循环
result = ListNode(0)
re = result
carry = 0
# l1,l2,进位 有一个存在则需要继续链表
while l1 or l2 or carry > 0:
x = l1.val if l1 else 0
y = l2.val if l2 else 0
re.next = ListNode((x + y + carry) % 10)
re = re.next
# 进位
carry = (x + y + carry) // 10
if l1 is not None:
l1 = l1.next
if l2 is not None:
l2 = l2.next
return result.next
这个是根据下面的那道题改的
class Solution:
def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
# write code here
head,c=l1,0
while l1 and l2:
_=l1.val+l2.val+c
l1.val=_%10
c=_//10
tail=l1
l1,l2=l1.next,l2.next
if l2:
tail.next=l2
while c>0 and l2:
_=l2.val+c
l2.val=_%10
c=_//10
tail=l2
l2=l2.next
elif l1:
while c>0 and l1:
_=l1.val+c
l1.val=_%10
c=_//10
tail=l1
l1=l1.next
if c>0:
c=ListNode(c)
tail.next=c
return head
12、链表相加(二)
一点都没看,但是这个就是上一道题的改编版,他需要先翻转一下,再相加,相加的结果再翻转就可以了
class Solution:
def reverse(self,head):
if not head or not head.next:return head
prev=head
curr=head.next
prev.next=None
while curr:
nxt=curr.next
curr.next,prev,curr=prev,curr,nxt
return prev
def addInList(self , head1: ListNode, head2: ListNode) -> ListNode:
# write code here
h1=self.reverse(head1)
h2=self.reverse(head2)
head,c=h1,0
while h1 and h2:
_=h1.val+h2.val+c
h1.val=_%10
c=_//10
tail=h1
h1,h2=h1.next,h2.next
if h2:
tail.next=h2
while c>0 and h2:
_=h2.val+c
h2.val=_%10
c=_//10
tail=h2
h2=h2.next
elif h1:
while c>0 and h1:
_=h1.val+c
h1.val=_%10
c=_//10
tail=h1
h1=h1.next
if c>0:
c=ListNode(c)
tail.next=c
return self.reverse(head)
13、单链表的排序
class Solution:
def sortInList(self , head: ListNode) -> ListNode:
# write code here
# 这个也是借助sort来排序的
if not head:# 空的时候直接就是排好的了
return
cur=head
res=[]
while cur:
res.append(cur.val)
cur=cur.next
res.sort()
dummy=ListNode(0)
pre=head
i=0
while pre:
pre.val=res[i]
pre=pre.next
i+=1
return head
14、判断一个链表是否为回文结构
学不明白链表,就借助列表
class Solution:
def isPail(self , head: ListNode) -> bool:
# write code here
res = []
cur = head
while cur:
res.append(cur.val)
cur = cur.next
return res == res[::-1]
15、链表的奇偶重排
class Solution:
def oddEvenList(self , head: ListNode) -> ListNode:
# write code here
if not head:return None
evenHead = head.next # 偶数的第一个
odd = head # 奇数
even = head.next # 偶数
while even and even.next:
odd.next = even.next # 奇数指向奇数
odd = odd.next
even.next = odd.next # 偶数指向偶数
even = even.next
odd.next = evenHead # 奇数最后一个指向偶数第一个
return head
16、删除有序链表中重复的元素-I(顺序排列)
class Solution:
def deleteDuplicates(self , head: ListNode) -> ListNode:
# write code here
# 按顺序排列的 所以可以直接比较就行
if not head: return None
slow,fast = head,head.next
while fast:
if fast.val != slow.val:# 不等就可以保留
slow.next = fast
slow = slow.next
fast = fast.next
slow.next = None
return head
17、删除有序链表中重复的元素-II(删除重复的所有东西)
class Solution:
def deleteDuplicates(self , head: ListNode) -> ListNode:
# write code here
res = ListNode(0)
res.next = head
fa = res
cur = head
while cur and cur.next:
if cur.val != cur.next.val:
fa = cur
cur = cur.next
else:
while cur.val==cur.next.val:
cur = cur.next
if not cur.next:
break
fa.next = cur.next
cur = cur.next
return res.next