文章目录
理论讲解
数组
数组,内存中连续的一段存储区域。
查找Access: O(1);
插入Insert: 平均 O(n);(最好的是O(1),最坏的是O(n),故而平均是O(n/2)即O(n));
Delete: 平均 O(n);(最好的是O(1),最坏的是O(n));
链表
链表应用场景:
①插入和删除操作频繁,不希望此操作浪费太多时间所作的改进;
②不知道表到底有多长,则可选用链表结构。
链表的操作:
插入和删除。图示,只需要两次操作,常数级,则复杂度为O(1);
查找是O(n);
所以没有一个数据结构是完美的,不同的算法和数据结构是博弈的关系,有地方是优势也有地方是劣势。
面试题
206.反转链表reverse-linked-list
思考的逻辑很简单,把每个结点的next指向它的前驱结点即可,基本上所有链表或者简单数据结构的题目所考的都不是思维能力,因为思维相对简单直接,主要考代码实现能力和代码的简洁程度。
这道题目,自然需要先定义两个指针,一个指向当前结点,一个指向当前结点的前驱结点。(python),注意输出的是pre,
覃超说:大家把反转链表的常用语句记住即可
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
res, p = None, head
while p:
res, res.next, p = p, res, p.next
return res
解释:
-
多元赋值的时候,右边的值不会随着赋值而改变~;
-
前置条件:迭代指针:p = head、结果指针:res = none
以1->2->3->4->5为例:
过程:
res:None
第一层循环
res:1->2->3->4->5 res = p
res:1->None res.next = res
p:2->3->4->5 p = p.next
第二层循环
res:2->3->4->5 res = p
res:2->1->None res.next = res
p:3->4->5 p = p.next
第三层循环
res:3->4->5 res = p
res:3->2->1->None res.next = res
p:4->5 p = p.next
第四层循环
res:4->5 res = p
res:4->3->2->1->None res.next = res
p:5 p = p.next
第五层循环
res:5 res = p
res:5->4->3->2->1->None res.next = res
p:None p = p.next
end…
141.环形链表linked-list-cycle
思考:
Ⅰ。硬做,卡下时间,一直循环,看是否会到NULL(无环会到NULL,有环不会到NULL);
Ⅱ。利用set数据结构判重,复杂度为O(n)(若判断set中有新结点,则是有环)
Ⅲ。利用快慢指针,快指针每次走两步,慢指针每次走一步,复杂度为O(n)(有环则会相遇,无环就不会),空间复杂度比Ⅱ好。
选择Ⅲ实现代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
pos = 1
fast=low=head
while fast and fast.next: # 不用要求low指针也不为空吧,这个条件多余?
low = low.next
fast = fast.next.next
if low == fast:
pos = -1
return pos
return pos
要注意循环终止条件:
①循环体为什么要求fast.next为true?是因为循环内部fast指针每次走两步,若fast指针指向最后一个结点,那么fast.next即为NULL,fast.next.next不存在,会显示非法错误,故而也要求循环体符合fast.next为ture的条件
②循环体为什么还要加上low指针不指向空的条件?在此理解为若输入链表为空时,那么low指针指向空,在循环时判断第一个条件即不符合不进入循环体,就不用往后循环了,节省时间当然留fast也可以满足该条件;或许是为了整齐而加上该条件?不加该条件leetcode也能运行,故而应该不是太重要的,所以不care了吧。
24.两两交换链表中的结点swap-nodes-in-pairs
偶数情况:1234–2143
奇数情况:12345–21435
所考思维相对简单直接,主要对代码实现能力要求较高(指链表这类题目),结合反转链表来理解做法。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
pre, pre.next = self, head
while pre.next and pre.next.next:
a = pre.next
b = a.next
pre.next, a.next, b.next = b, b.next, a
pre = a
return self.next #不理解,有点懂了,找第一个结点,此时是self.next