Leetcode 题目
Day 1:
1、最长前缀
思路一:只需比较ASCI结果最大和最小字符串的公共前缀即可
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if len(strs) == 0: return ""
strs_min = min(strs)
strs_max = max(strs)
for i, x in enumerate(strs_min):
if x != strs_max[i]:
return strs_max[:i]
return strs_min
思路二:遍历两两依次比较
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
pre, count = strs[0], len(strs)
for i in range(1, count):
pre = self.lcp(pre, strs[i])
if not pre:
break
return pre
def lcp(self, str1, str2):
n, idx = min(len(str1), len(str2)), 0
while idx < n and str1[idx] == str2[idx]: # 通过while循环和for循环相比,不会跳过中间不等的情况【air, abr】
idx += 1
return str1[:idx]
2、括号匹配问题
思路:通过栈来实现既考虑到括号出现的顺序也考虑到括号的个数。如果一个括号满足条件将其弹出去;不满足就返回False
class Solution:
def isValid(self, s: str) -> bool:
rule = {')':'(', ']':'[', '}':'{'}
stack = []
for item in s:
if item in rule:
if not stack or stack[-1] != rule[item]:
return False
stack.pop()
else:
stack.append(item)
return not stack
3、链表按照顺序合并
思路:
1、依次比较L1和L2中比较小的节点,将小的节点进行合并。
2、最终有一个链表没有合并完的节点连接到prev.next之后即可
3、返回虚拟节点的下一个节点(永远指向头节点)
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
prehead = ListNode(-1)
prev = prehead
while l1 and l2:
if l1.val <= l2.val:
prev.next = l1
l1 = l1.next
else:
prev.next = l2
l2 = l2.next
prev = prev.next
# 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 if l1 is not None else l2
return prehead.next
4、链表部分反转
方法一:
1、将left 到 right 之间的链表反转
2、再和原来的链表相连
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
# 反转链表
def reverse_sublk(head):
pre = None
cur = head
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
# 定义虚拟节点
dummy_node = ListNode(-1)
dummy_node.next = head
pre = dummy_node
# 将pre移动到left之前
for _ in range(left - 1):
pre = pre.next
# 获取right_node节点
right_node = pre
for _ in range(right - left + 1):
right_node = right_node.next
# 获取子链表
left_node = pre.next
cur = right_node.next
# 与原链表断开
pre.next = None
right_node.next = None
# 反转子链表
reverse_sublk(left_node)
# 反转后的子链表与原链表连接
pre.next = right_node
left_node.next = cur
return dummy_node.next
方法二:
1、按照头插法的方式,将left + 1到 right 之间的节点都插到left之前即可
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
# 设置虚拟节点
dummy_node = ListNode(-1)
dummy_node.next = head
pre = head
# 将pre移动到left之前
for - in range(left - 1):
pre = pre.next
# 反转列表
cur = pre.next
for _ in range(right - left):
# 保存当前节点的下一个节点
tmp = cur.next
# 将当前节点与下下一个节点相连
cur.next = tmp.next
# 将tmp节点插到头节点前面
tmp.next = pre.next
# 更新pre.next, 保证下一次插入
pre.next = tmp
return dummy_node.next