240.搜索二维矩阵II
一、自己写的史山代码(超时)
看到自己写的代码就好笑。。像刚进大学学C语言时会写出来的...感觉白读几年书。。。但还是记录一下,可以忽略这个
python
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
m, n = len(matrix), len(matrix[0])
idx_i, idx_j = 0, 0
flag = False
while idx_i < m and idx_j < n:
if matrix[idx_i][idx_j] == target:
flag = True
break
for i in range(m):
if matrix[i][idx_j] < target:
continue
if matrix[i][idx_j] == target:
idx_i = i
flag = True
break
if matrix[i][idx_j] > target:
idx_i = i
break
while idx_j >= 0 and matrix[idx_i][idx_j] > target:
if matrix[idx_i][idx_j] == target:
flag = True
break
idx_j -= 1
return flag
二、二叉搜索树
思路:
二叉搜索树是指根节点的左子树的值都小于根节点,右子树的值都大于根节点,考虑把整个矩阵逆时针旋转45度从上到下就相当于是一个二叉搜索树。后续若target大了就向左遍历找更小值,小了就向右遍历找更大值。
代码:
python
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
i, j = 0, len(matrix[0]) - 1
while i < len(matrix) and j >= 0:
if matrix[i][j] < target: i += 1
elif matrix[i][j] > target: j -= 1
else: return True
return False
160.相交链表
自己没想出来。。看的题解
参考:
举例理解:
假设链表 headA 和 headB 如下:
headA: A0 -> A1 -> A2 -> C0 -> C1 -> C2
headB: B0 -> B1 -> B2 -> C0 -> C1 -> C2
其中,C0 是交点。则有:
- 指针 A 的路径:A0 -> A1 -> A2 -> C0 -> C1 -> C2 -> B0 -> B1 -> B2 -> C0
- 指针 B 的路径:B0 -> B1 -> B2 -> C0 -> C1 -> C2 -> A0 -> A1 -> A2 -> C0
可以看到,两个指针最终在 C0 处相遇。
如果没有交点,假设链表如下:
headA: A0 -> A1 -> A2
headB: B0 -> B1 -> B2
则有:
- 指针 A 的路径:A0 -> A1 -> A2 -> B0 -> B1 -> B2 -> None
- 指针 B 的路径:B0 -> B1 -> B2 -> A0 -> A1 -> A2 -> None
两个指针最终同时到达 None,表示没有交点。
注意:
参考链接里面的虽然能通过,但是我理解他给出的代码是建立在两个链表若存在相交点,必然从这一点及之后节点都完全相同,但题目貌似没给出这个条件。所以自己在原代码的基础上加入了一些判断条件,如果后面的节点存在不相同的都返回None。
代码:
python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
A, B = headA, headB
while A != B:
A = A.next if A else headB
B = B.next if B else headA
# 检查从交点开始的节点是否完全相同
if A is None:
return None
# 从交点开始检查
currentA, currentB = A, A
while currentA and currentB:
if currentA != currentB:
return None # 从交点开始的节点不完全相同
currentA = currentA.next
currentB = currentB.next
return A # 从交点开始的节点完全相同
206.反转链表
一、双指针法
思路:
1、cur指针指向当前节点,pre指针指向该节点前一节点
2、cur初始化为头节点,pre初始化为None,因为需要反转链表,头节点的下一个翻转过来指向的就是None
3、注意链表修改顺序,先用temp变量暂存cur.next,后续修改cur指向pre,再依次移动cur、pre
代码:
python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 1->2->3->None 反转后相当于
# None<-3<-2<-1 所以pre设置为None
cur = head
pre = None
while cur:
# 先存cur.next,因为后面会修改为next指向pre,然后按顺序修改指针指向
temp = cur.next
cur.next = pre
pre = cur
cur = temp
return pre
复杂度分析:
- 时间复杂度:O(N)
- 空间复杂度:O(1)
二、递归法
递归三部曲:
1、确定递归函数的参数和返回值:参数------当前节点和前一节点;返回值------反转后的头节点,也就是遍历完的pre(不是cur,因为此时cur已经指向None了)
2、确定终止条件:当cur == None时,返回pre
3、确定单层递归逻辑:cur.next指向pre,同时节点不断往后走
代码:
python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def reverse(cur, pre):
# 终止条件
if cur == None:
return pre
temp = cur.next
cur.next = pre
return reverse(temp, cur)
return reverse(head, None)
复杂度分析:
- 时间复杂度O(N):遍历链表为线性时间大小
- 空间复杂度O(N):遍历链表的递归深度达到 N ,系统使用 O(N) 大小额外空间
参考: