剑指Offer11-旋转数组的最小数字
输入:[3,4,5,1,2]
输出:1
class Solution:
def minArray(self, numbers: List[int]) -> int:
# 方法1:无论如何旋转,最小值不变
return min(numbers)
# 方法2:顺序查找,找到最小值
minNum = numbers[0]
for i in range(1, len(numbers)):
if numbers[i] < minNum:
minNum = numbers[i]
return minNum
# 方法3:二分查找
low = 0
high = len(numbers) - 1
while low < high:
mid = low + (high-low)//2
if numbers[mid] < numbers[high]:
high = mid
elif numbers[mid] > numbers[high]:
low = mid + 1
else:
high -= 1
return numbers[low]
189-旋转数组
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
- 方法1:使用辅助数组
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
# 方法1
res = []
length = len(nums)
key = length - (k % length) # 关键取余数操作
for i in range(key,length,1):
res.append(nums[i])
for j in range(key):
res.append(nums[j])
nums[:] = res
# 方法2
res = []
length = len(nums)
key = length - (k % length)
res = nums[key:] + nums[:key]
nums[:] = res
- 方法2:原地交换
剑指Offer53-在排序数组中查找数字
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
解释: 8在排序数组中出现了2次
class Solution:
def search(self, nums: List[int], target: int) -> int:
# 方法1:顺序查找
# res = 0
# for num in nums:
# if num == target:
# res += 1
# return res
# 方法2:二分查找
# 1 搜索右边界,右边界的左侧都是 <= target 的数
left = 0
right = len(nums) - 1
while left <= right:
mid = left + (right-left)//2
if nums[mid] > target:
right = mid - 1
else:
left = mid + 1
rightNum = left
# 如果数组中没有target,则提前返回
if right >= 0 and nums[right] != target:
return 0
# 2 搜索左边界
left = 0
right = len(nums) - 1
while left <= right:
mid = left + (right-left)//2
if nums[mid] < target:
left = mid + 1
else:
right = mid - 1
leftNum = right
return rightNum - leftNum - 1
566-重塑数组
输入:mat = [[1,2],[3,4]], r = 1, c = 4
输出:[[1,2,3,4]]
- 寻找映射关系
# 映射关系:
# 行:r = i//col 取整数
# 列:c = i % col 取余数
class Solution:
def matrixReshape(self, mat: List[List[int]], r: int, c: int) -> List[List[int]]:
row = len(mat)
col = len(mat[0])
if row*col != r*c:
return mat
res = [[0 for i in range(c)] for j in range(r)]
for i in range(row*col):
res[i//c][i%c] = mat[i//col][i%col]
return res
3-无重复字符的最长子串
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
- 动态规划+哈希表
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
hashMap = {}
left = 0
maxLen = 0
for index, val in enumerate(s):
if val in hashMap:
left = max(left, hashMap[val]+1)
hashMap[val] = index
maxLen = max(maxLen, index-left+1)
return maxLen
21-合并两个有序的链表
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
- 方法1:使用递归
递归表达式——总结出子问题
情况1: list1[0] + merge(list[1:], list2[0]) if list1[0] < list2[0]
情况2: list2[0] + merge(list[0], list2[1:]) if list1[0] >= list2[0]
特别情况:当l1 或者 l2 是空链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 is None:
return l2
elif l2 is None:
return l1
elif l1.val < l2.val: # 先连上较小的数
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
elif l1.val >= l2.val:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
- 方法2:使用迭代
思路:当l1和l2都不是空链表时,判断l1和l2哪一个链表的头结点的值更小,将较小值的节点添加到结果里面,当一个节点被添加到结果里面之后,将对应链表中的节点向后移动一位
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
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
19-删除链表的倒数第n个结点
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
- 方法1:使用双指针
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# 双指针
dummy = ListNode(0,head) # 哑结点
slow = dummy
fast = head
for i in range(n): # slow和fast中间相隔两个 n 个结点
fast = fast.next
while fast is not None: # 当fast到达末尾,slow所指的下一个节点将被删除
slow = slow.next
fast = fast.next
# 删除节点元素
slow.next = slow.next.next
return dummy.next
网友评论