目录
前言
提示:对环境必须筛选挑剔,否则必然潜移默化的被周边的价值观和各种微小习惯拉下水,拒绝的越早,越容易独善其身。纠缠的时间越长摆脱的阻力越大,甚至没有意识到要摆脱,那就彻底没救了。
本系列《绝境求生》记录转码算法筑基过程,以代码随想录为纲学习,leetcode_hot_100练手,在此记录思考过程,方便过后复现。内容比较粗糙仅便于笔者厘清思路,复盘总结。
我突然觉得前两篇文章模型不够规范。我在努力想一个万能的解题模型
比如:
简单理解?
能不能用图示意?
初始化条件?
边界条件?
用什么方法:暴力法/ 其它巧妙的优化法。
巧妙方法的子思路是?
。。。。。??
细节?
之前见过但没注意到的?
新知识?
提示:以下是本篇文章正文内容
一、206 反转链表
1.模型
简单理解?
把head变成tail, tail变成head
能不能用图示意?
编辑
[pre(None)->cur(1)->temp(2)->3->None]
初始化条件?
解决函数里,cur=head,pre=None, 最后返回pre
边界条件?
只有一层循环
知道while 这个行为本身不会改变cur,只是在不停地判断cur是否为None
用什么方法:暴力法/ 其它巧妙的方法。 巧妙方法的子思路是? 。。。。。??
双指针法 当前指针cur和前一个节点指针pre
"""
把tail变成head
初始化 cur指向next,pre为null,然后把cur用temp存放一下,然后让cur.next指向pre,循环这个过程
双指针法 前一个节点pre 和当前节点 cur
指针题模版:定义节点,列表转链表,画链表图 cur(1)head->2->3->None,初始化指针节点
"""
class ListNode:
def __init__(self,val=0,next=None):
self.val=val
self.next=next
def create_link_list(list):
if not list:
return None
head=ListNode(list[0])
cur=head
for val in list[1:]: #给创造下一个节点,需要新的值,再用cur.next存放下一个节点。再用cur=cur.next串联下一个节点
cur.next=List[val]
cur=cur.next
return head
class solution:
def reverselist(self,head:ListNode)->ListNode:
#初始化双指针
cur=head
pre=None
while cur: #只要cur不为None 就说明还有节点没有处理继续循环
temp=cur.next #保存cur的下一个节点(因为等下要改cur.next,会丢地址),当前cur=1,cur.next=2,等一下cur.next=pre 就找不到2了 [pre(None)->cur(1)->temp(2)->3->None]
#反转当前节点的指向
cur.next=pre
#指向完后 要移动位置 pre和cur都要往前走
pre=cur
cur=temp
return pre #循环结束,返回新的头节点
细节?
None
之前见过但没注意到的?
伪代码或者是数据流动图中的null,在python中就是None。
疑惑点/新知识 ?
链表的反转感觉就是再改指针指向
while cur 本质上是判断条件,不是更新操作 ?
- 它只检查当前的
cur是不是None:如果cur指向一个节点(非空),就执行循环体;如果cur是None(没节点了),就退出循环。 - 它不会主动改变
cur的值
cur是怎么推进的 ?
pre=cur
cur=temp # 因为之前用temp=cur.next
二、234 回文链表
题目描述
给你一个单链表的头节点 head,请你判断该链表是否为回文链表。如果是,返回 true;否则,返回 false。
示例
- 示例 1:输入:
head = [1,2,2,1]→ 输出:true(链表反转后和原链表一致) - 示例 2:输入:
head = [1,2]→ 输出:false(反转后是 [2,1],和原链表不一致)
提示
- 链表中节点数目在范围
[1, 10^5]内 - 节点值范围
[0, 9] - 进阶:能否用 O (n) 时间复杂度和 O (1) 空间复杂度解决?
1.模型
简单理解?
就是看起来这个链表是前后对称的
能不能用图示意?
None
初始化条件?
None
边界条件?
None
用什么方法:暴力法/ 其它巧妙的方法。 巧妙方法的子思路是? 。。。。。??
暴力法
列表虽然不能用索引访问,我们就用数组来存链表的值 再用相向双指针来判断数组的值一不一样 就可以知道是不是回文数组。
缺点:需要额为数组存储,时间复杂度是 链表的长度 On
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
cur=head
l=[]
while cur:
l.append(cur.val)
cur=cur.next
left,right=0,len(l)-1
while left<right:
if l[right]==l[left]:
left+=1
right-=1
else:
return False
return True
优化法
先用快慢指针找到中点,然后用反转链表法把后半段链表反转,然后对比前后两段是不是一样的
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
# 如果链表只有一个元素head.next = None 或者为空 那它就是回文链表
if not head or not head.next:
return True
# 1用快慢指针找链表中点(慢指针最终指向中点前一个节点)
slow = head # 慢指针:每次走1步
fast = head # 快指针:每次走2步
while fast.next and fast.next.next: # 快指针能走2步时才继续
slow = slow.next # 慢指针走1步
fast = fast.next.next # 快指针走2步
# 2反转后半段链表(从slow.next开始反转)
# 反转函数(和之前学的双指针反转链表一致)
def reverselist(self,head:ListNode)->ListNode:
#初始化双指针
cur=head
pre=None
while cur: #只要cur不为None 就说明还有节点没有处理继续循环
temp=cur.next #保存cur的下一个节点(因为等下要改cur.next,会丢地址),当前cur=1,cur.next=2,等一下cur.next=pre 就找不到2了 [pre(None)->cur(1)->temp(2)->3->None]
#反转当前节点的指向
cur.next=pre
#指向完后 要移动位置 pre和cur都要往前走
pre=cur
cur=temp
return pre #循环结束,返回新的头节点
#buer 这对吗 我刚做这道题啊 爽用
reversed_half = reverselist(slow.next) # 反转后半段,得到新表头
# 3对比前半段和反转后的后半段
p1 = head # p1:前半段的指针(从表头开始)
p2 = reversed_half # p2:反转后半段的指针(从反转后的表头开始)
result = True # 先假设是回文,后续对比失败再改
while p2: # 只要p2不为空(后半段没对比完)
if p1.val != p2.val: # 对应值不相等,不是回文
result = False
break
p1 = p1.next # p1前进
p2 = p2.next # p2前进
# 4多做一步。恢复原链表 因为刚刚不是修改了原来的链表了吗
slow.next = reverselist(reversed_half)
return result
细节?
忘记cur的形状 任何都可以替代cur 不要学太死,可以用slow fast替代cur
之前见过但没注意到的?
只有要用列表构建链表的时候才用到 cur.next=ListNode(val) val=1,2,3,.....n
题目给的模式head本身就是个链表不需要再构建
疑惑点/新知识?
如果链表只有一个元素head.next = None 或者为空 那它就是回文链表
if not head or not head.next:
return True
快指针走两步,慢指针走一步。快指针走到头退出循环的时候这时候的慢指针指向的就是终点
``
-
链表 [1→2→2→1](偶数情况):
- 初始:slow=1,fast=1
- 第一次循环:slow=2,fast=2(fast.next=1,fast.next.next=None → 循环结束)
- 最终:slow=2(中点前一个节点),后半段从 slow.next=2 开始
-
链表 [1→2→3→2→1](奇数情况):
- 初始:slow=1,fast=1
- 第一次循环:slow=2,fast=3(fast.next=2,fast.next.next=1 → 继续)
- 第二次循环:slow=3,fast=1(fast.next=None → 循环结束)
- 最终:slow=3(中点节点),后半段从 slow.next=2 开始(跳过中点,不影响回文判断)

编辑
最近沉迷ai suanming,该说不说给我整高潮了,我要继续努力~