defsuo_yin(nums, target):
left =0
right =len(nums)-1while left <= right:
mid =(right + left)//2if nums[mid]== target:return mid
elif nums[mid]< target:
left = mid +1else:
right = mid -1
nums.insert(left, target)#insert:插入函数return left
nums =input("请输入一串数组 ").split(",")
nums =list(map(int, nums))
target =int(input("要找的数"))
result = suo_yin(nums, target)print(result)print(nums)
2.给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
defmySqrt(x):"""
:type x: int
:rtype: int
"""if x ==0:return0
left, right =1, x
while left <= right:
mid =(left + right)//2if mid * mid == x:return mid
elif mid * mid > x:
right = mid -1else:
left = mid +1return right
x =int(input("请输入一个数"))
result = mySqrt(x)print("%d的算术平方根为%d"%(x,result))
defisPerfectSquare(num):if num ==0:returnFalse
left, right =0, num
while left <= right:
mid =(left + right)//2if mid * mid == num:returnTrueelif mid * mid > num:
right = mid -1else:
left = mid +1returnFalse
num =int(input("请输入一个数:"))
result = isPerfectSquare(num)print(result)
defsortedSquares(nums):
n =len(nums)
result =[0]* n
left, right =0, n -1
index = n -1while left <= right:if nums[left]**2> nums[right]**2:
result[index]= nums[left]**2
left +=1else:
result[index]= nums[right]**2
right -=1
index -=1return result
nums =input("请输入一个非递减数列:").split(",")
nums =list(map(int, nums))
result = sortedSquares(nums)print(result)
三.长度最小的子数组
8.给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
defjie_fa(s, nums):
fast =0
slow =0
n =len(nums)sum=0
min_len =float('intf')while fast < n:sum+= nums[fast]whilesum>= s:
min_len =min(min_len, fast - slow +1)sum-= nums[slow]
slow +=1
fast +=1if min_len ==float('inf'):return0else:return min_len
9.你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
10.给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
defmin_window(s:str, t:str)->str:from collections import Counter
target = Counter(t)
window ={}
left =0
right =0match=0
min_len =float('inf')
start =0while right <len(s):
c = s[right]if c in target:
window[c]= window.get(c,0)+1if window[c]== target[c]:match+=1
right +=1# 缩小窗口whilematch==len(target):if right - left < min_len:
min_len = right - left
start = left
c = s[left]if c in target:
window[c]-=1if window[c]< target[c]:match-=1
left +=1if min_len !=float('inf'):return s[start:start + min_len]else:return''
from typing import List
defgenerate_matrix(n:int)-> List[List[int]]:# 创建二维数组
matrix =[[0]* n for _ inrange(n)]
top, bottom =0, n -1# 上下边界
left, right =0, n -1# 左右边界
num =1# 当前要填充的数字while top <= bottom and left <= right:# 填充上边for i inrange(left, right +1):
matrix[top][i]= num
num +=1
top +=1# 填充右边for i inrange(top, bottom +1):
matrix[i][right]= num
num +=1
right -=1# 填充下边if top <= bottom:for i inrange(right, left -1,-1):
matrix[bottom][i]= num
num +=1
bottom -=1# 填充左边if left <= right:for i inrange(bottom, top -1,-1):
matrix[i][left]= num
num +=1
left +=1return matrix
defprint_matrix(matrix: List[List[int]]):for row in matrix:print(' '.join(str(i)for i in row))
n =5
matrix = generate_matrix(n)
print_matrix(matrix)
二.链表
1.移除链表元素
12.题意:删除链表中等于给定值 val 的所有节点。
方法一.虚拟头结点
from typing import Any
classListNode:def__init__(self, val=0,next=None):
self.val = val
self.next=nextdefremoveElements(head: ListNode, val:int)-> ListNode |None| Any:# 创建虚拟头节点
dummy = ListNode(-1)
dummy.next= head
curr = dummy
while curr.next:if curr.next.val == val:
curr.next= curr.next.nextelse:
curr = curr.nextreturn dummy.nextdefprintLinkedList(head: ListNode)->None:
result =[]while head:
result.append(head.val)
head = head.nextprint(result)
head = ListNode(6, ListNode(2, ListNode(6, ListNode(3, ListNode(4, ListNode(5, ListNode(6)))))))
val =6
head = removeElements(head, val)
printLinkedList(head)
方法二.
from typing import Any
classListNode:def__init__(self, val=0,next=None):
self.val = val
self.next=nextdefremoveElements(head: ListNode, val:int)-> ListNode |None| Any:# 处理链表为空的情况ifnot head:returnNone# 处理头部节点等于 val 的情况# while head.val == val:# head = head.next
curr = head
while curr and curr.next:if curr.next.val == val:
curr.next= curr.next.nextelse:
curr = curr.nextreturn head
defprintLinkedList(head: ListNode)->None:
result =[]while head:
result.append(head.val)
head = head.nextprint(result)
head = ListNode(6, ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5, ListNode(6)))))))
val =6while head.val == val:
head = head.next
removeElements(head, val)
printLinkedList(head)
题意:
13.在链表类中实现这些功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
classMyLinkedList:def__init__(self):
self.head =None# 链表头节点指针,默认为空
self.length =0# 链表长度,默认为0defget(self, index:int)->int:"""
获取链表中第 index 个节点的值。如果索引无效,则返回-1。
"""if index <0or index >= self.length:# 索引无效,返回-1return-1
curr = self.head
for _ inrange(index):
curr = curr.next# 遍历链表,找到对应索引的节点return curr.val
defaddAtHead(self, val:int)->None:"""
在链表的第一个元素之前添加一个值为 val 的节点。
插入后,新节点将成为链表的第一个节点。
"""
newNode = ListNode(val)# 创建新节点
newNode.next= self.head # 将新节点的 next 指针指向原先的头节点
self.head = newNode # 将新节点设置为头节点
self.length +=1defaddAtTail(self, val:int)->None:"""
将值为 val 的节点追加到链表的最后一个元素。
"""
newNode = ListNode(val)# 创建新节点ifnot self.head:# 如果链表为空,将新节点设置为头节点
self.head = newNode
else:
curr = self.head
while curr.next:# 找到链表的最后一个节点
curr = curr.next
curr.next= newNode # 将新节点连接到最后一个节点的 next 指针上
self.length +=1defaddAtIndex(self, index:int, val:int)->None:"""
在链表中的第 index 个节点之前添加值为 val 的节点。
如果 index 等于链表的长度,则该节点将附加到链表的末尾。
如果 index 大于链表长度,则不会插入节点。
如果 index 小于0,则在头部插入节点。
"""if index <0or index > self.length:# 索引无效,不插入节点returnif index ==0:# 在头部插入节点
self.addAtHead(val)returnif index == self.length:# 在末尾插入节点
self.addAtTail(val)return
newNode = ListNode(val)# 创建新节点
curr = self.head
for _ inrange(index -1):# 找到插入位置的前一个节点
curr = curr.next
newNode.next= curr.next# 将新节点的 next 指针指向原先索引位置的节点
curr.next= newNode # 将前一个节点的 next 指针指向新节点
self.length +=1defdeleteAtIndex(self, index:int)->None:"""
如果索引 index 有效,则删除链表中的第 index 个节点。
"""if index <0or index >= self.length:# 索引无效,不删除节点returnif index ==0:# 删除头节点
self.head = self.head.nextelse:
curr = self.head
for _ inrange(index -1):# 找到要删除节点的前一个节点
curr = curr.next
curr.next= curr.next.next# 将前一个节点的 next 指针指向要删除节点的下一个节点
self.length -=1
from collections import Counter
defkuai_le_shu(num):sum=0while num >0:
i = num %10
num = num //10sum+= i * i
returnsum
num =7
slow = num
fast = kuai_le_shu(num)while slow != fast and fast !=1:
slow = kuai_le_shu(slow)
fast = kuai_le_shu(kuai_le_shu(fast))if fast ==1:print("true")else:print("false")
这段代码的时间复杂度和空间复杂度如下:
时间复杂度:在最坏情况下,输入的数不是快乐数,且最终会进入一个循环。假设输入的数有 d 位数字,那么计算每个位上数字的平方和的时间复杂度是 O(d),而每次更新快慢指针的时间复杂度是 O(1)。因此,总的时间复杂度是 O(d * k),其中 k 是循环的次数。由于循环次数是有限的,所以时间复杂度可以看作是 O(d)。
空间复杂度:这段代码的空间复杂度主要取决于存储中间计算结果的变量。在计算每个位上数字的平方和时,使用了一个变量 sum 存储中间结果,因此空间复杂度是 O(1)。此外,还使用了两个变量 slow 和 fast 来保存快慢指针的值,它们只是用来追踪计算过程中的状态,不随输入规模变化,所以也可以看作是 O(1) 的空间复杂度。
defthreeSum(nums, target):
nums.sort()# 对数组进行排序,便于跳过重复元素和确定左右指针移动的方向
n =len(nums)# 数组的长度
res =[]# 存储结果的列表for i inrange(n -2):# 遍历数组,i 最多到倒数第三个位置if nums[i]> target:# 如果第一个元素已经大于 target,则直接返回结果return res
if i >0and nums[i]== nums[i -1]:# 跳过重复的第一个数,避免重复计算continue
left = i +1# 左指针初始位置为 i 的下一个位置
right = n -1# 右指针初始位置为数组末尾while left < right:# 当左指针小于右指针时进行循环
total = nums[i]+ nums[left]+ nums[right]# 计算当前三个数的和if total == target:# 如果和等于目标值
res.append([nums[i], nums[left], nums[right]])# 将结果添加到 res 中while left < right and nums[left]== nums[left +1]:# 跳过重复的第二个数,避免重复计算
left +=1while left < right and nums[right]== nums[right -1]:# 跳过重复的第三个数,避免重复计算
right -=1
left +=1# 移动左指针到下一个位置
right -=1# 移动右指针到前一个位置elif total < target:# 如果和小于目标值,移动左指针增大和
left +=1else:# 如果和大于目标值,移动右指针减小和
right -=1return res # 返回结果列表
nums =[-1,0,1,2,-1,-4]# 示例输入数组
target =0# 示例目标值
result = threeSum(nums, target)# 调用函数进行三数之和查找print(result)# 打印结果
四.字符串:
23.给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = “abcdefghijklmn”, k = 4
输出: “dcbaefghlkjimn”
defreverseString(s, k):# 计算s的长度除以2k的余数
m =len(s)%(2* k)# 计算最后一个完整的2k长子字符串结束的索引n
n =len(s)- m -1# 反转每个2k长子字符串,从索引0开始,步长为2kfor i inrange(0, n,2* k):
left = i
right = i + k -1while left < right:# 交换左右索引的字符
s[left], s[right]= s[right], s[left]
left +=1
right -=1# 如果剩余子字符串的长度m小于k,则反转该字符串if m < k:
left = n +1
right =len(s)-1while left < right:# 交换左右索引的字符
s[left], s[right]= s[right], s[left]
left +=1
right -=1else:# 如果剩余子字符串的长度m大于等于k,则反转该字符串的前k个字符
left = n +1
right = n + k
while left < right:# 交换左右索引的字符
s[left], s[right]= s[right], s[left]
left +=1
right -=1# 将字符数组转换为字符串并返回return''.join(s)# 示例输入
input_str ="abcdefghijklmn"
input_str =list(input_str)# 将字符串转换为字符数组
k =4
result = reverseString(input_str, k)print(result)# 打印反转后的结果
24.给定一个字符串,逐个翻转字符串中的每个单词。
示例 1:
输入: “the sky is blue”
输出: “blue is sky the”
defreverseString(s):
n =len(s)-1
left =0
right = n
fast = slow =0while left < right:
s[left], s[right]= s[right], s[left]
left +=1
right -=1
s.append(' ')for i inrange(len(s)):if s[i]==' ':
fast = i -1while slow < fast:
s[slow], s[fast]= s[fast], s[slow]
slow +=1
fast -=1
slow = i +1return''.join(s)# 示例输入
input_str ="hello world!"
input_str =list(input_str)# 将字符串转换为字符数组
result = reverseString(input_str)print(result)# 打印反转后的结果
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
defrightRotateString(s, k):# 获取字符串长度
n =len(s)# 特判:如果字符串为空或者 k 小于等于 0 或者 k 大于等于字符串长度,则不需要旋转,直接返回原字符串ifnot s or k <=0or k >= n:return s
# 将字符串转换为列表
s =list(s)# 计算需要旋转的部分的长度
rotate_len = n - k
# 对前一部分进行反转
left =0
right = rotate_len -1while left < right:
s[left], s[right]= s[right], s[left]
left +=1
right -=1# 对后一部分进行反转
left = rotate_len
right = n -1while left < right:
s[left], s[right]= s[right], s[left]
left +=1
right -=1# 反转整个字符串
s.reverse()# 将列表转换为字符串并返回结果return''.join(s)# 示例输入
k =2
s ="abcdefg"
result = rightRotateString(s, k)print(result)# 打印右旋转后的字符串
classTreeNode:def__init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
deflevelOrder(root):ifnot root:return[]
result =[]defhelper(node, level):iflen(result)== level:
result.append([])
result[level].append(node.val)if node.left:
helper(node.left, level +1)if node.right:
helper(node.right, level +1)
helper(root,0)return result
root = TreeNode(6)
root.left = TreeNode(4)
root.right = TreeNode(7)
root.left.left = TreeNode(2)
root.left.right = TreeNode(3)
root.right.left = TreeNode(5)
root.right.right = TreeNode(8)
result = levelOrder(root)print(result)
37.给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
classTreeNode:def__init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
deflevelOrder(root):
result =[]
level =0ifnot root:return[]defhelper(node, level):iflen(result)== level:
result.append([])
result[level].append(node.val)if node.left:
helper(node.left, level +1)if node.right:
helper(node.right, level +1)
helper(root, level)return result
root = TreeNode(6)
root.left = TreeNode(4)
root.right = TreeNode(7)
root.left.left = TreeNode(2)
root.left.right = TreeNode(3)
root.right.left = TreeNode(5)
root.right.right = TreeNode(8)
end =[]
result = levelOrder(root)for seq in result:
end.append(seq[-1])print(end)
38.给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
classTreeNode:def__init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
deflevelOrder(root):
result =[]
level =0ifnot root:return[]defhelper(node, level):iflen(result)== level:
result.append([])
result[level].append(node.val)if node.left:
helper(node.left, level +1)if node.right:
helper(node.right, level +1)
helper(root, level)return result
root = TreeNode(6)
root.left = TreeNode(4)
root.right = TreeNode(7)
root.left.left = TreeNode(2)
root.left.right = TreeNode(3)
root.right.left = TreeNode(5)
root.right.right = TreeNode(8)
end =[]
result = levelOrder(root)for seq in result:sum=0
count =0for inseq in seq:sum+= inseq
count +=1
end.append(sum/count)print(end)print(result)
39.给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。
classNode:def__init__(self, val=None, children=None):
self.val = val
self.children = children if children isnotNoneelse[]# 递归实现层序遍历deflevelOrder(root):
result =[]ifnot root:return result
defdfs(node, level):iflen(result)== level:
result.append([])
result[level].append(node.val)for child in node.children:
dfs(child, level +1)
dfs(root,0)return result
# 构造一个N叉树并进行层序遍历
tree = Node(1,[Node(3,[Node(5), Node(6)]),
Node(2),
Node(4,[Node(7), Node(8)])])print(levelOrder(tree))
注意: self.children = children if children is not None else []
如果 children 不为 None,则将 children 赋值给 self.children。
classSolution:defcombine(self, n:int, k:int)-> List[List[int]]:# 定义回溯函数defbacktrack(combination, start, k):# 如果 k 等于 0,表示已经生成了一个长度为 k 的组合,将其添加到结果列表中if k ==0:
result.append(combination[:])# 将当前组合的副本加入结果列表return# 遍历可选的数字范围for i inrange(start, n +1):
combination.append(i)# 将当前数字 i 添加到组合中
backtrack(combination, i +1, k -1)# 递归调用,更新起始位置和 k
combination.pop()# 回溯,将最后添加的数字移除,尝试下一个数字
result =[]# 初始化结果列表
backtrack([],1, k)# 调用回溯函数,传入空的组合、起始位置为 1、需要生成的数字个数为 kreturn result # 返回结果列表
classSolution:defcombinationSum3(self, k:int, n:int)-> List[List[int]]:defbacktrack(start, k, n, path):# 当 k 和 n 都为 0 时,表示已经生成了一个满足条件的组合,将其添加到结果列表中if k ==0and n ==0:
result.append(path[:])# 将当前组合的副本加入结果列表return# 当 k 或 n 小于 0 时,表示当前组合不符合要求,直接返回if k <0or n <0:return# 遍历可选的数字范围,起始位置从 start 开始,上限为 9for i inrange(start,10):
path.append(i)# 将当前数字 i 添加到组合中# 递归调用,更新起始位置、k 和 n
backtrack(i +1, k -1, n - i, path)
path.pop()# 回溯,将最后添加的数字移除,尝试下一个数字
result =[]# 初始化结果列表
backtrack(1, k, n,[])# 调用回溯函数,传入起始位置为 1、需要生成的数字个数为 k、目标和为 n 的参数return result # 返回结果列表
例如:"0.1.2.201" 和 "192.168.1.1" 是 有效的 IP 地址,但是"0.011.255.245"、"192.168.1.312" 和 "192.168@1.1"是 无效的 IP 地址。
from typing import List
classSolution:defrestoreIpAddresses(self, s:str)-> List[str]:defbacktrack(start, path, parts):if start ==len(s)and parts ==4:
res.append(".".join(path))returnif parts >4:returnfor end inrange(start +1,min(start +4,len(s)+1)):if s[start:end]and0<=int(s[start:end])<=255and(s[start:end]=="0"or s[start]!="0"):
backtrack(end, path +[s[start:end]], parts +1)
res =[]
backtrack(0,[],0)return res
classSolution:defpermuteUnique(self, nums: List[int])-> List[List[int]]:defbacktrack(start, path):iflen(path)==len(nums):
res.append(path[:])returnfor i inrange(len(nums)):if used[i]or(i >0and nums[i]== nums[i-1]andnot used[i-1]):continue
used[i]=True
path.append(nums[i])
backtrack(i+1, path)
used[i]=False
path.pop()
res =[]
used =[False]*len(nums)
nums.sort()
backtrack(0,[])return res
该题需要先对数组进行排序,确保相同的数字是挨在一起的,然后会定义一个数组used(该数组长度和传入的数组相同),接着使用一个 for 循环遍历数组 nums,对于每个元素,检查是否已经被使用过或者之前的相同元素还未被使用,如果是,则跳过当前循环,避免生成重复的排列当递归返回后(即回溯到上一层),需要将当前元素的使用状态重置,并且将其从当前部分排列中移除,以便进行下一次尝试。
classSolution:defsolveNQueens(self, n:int)-> List[List[str]]:defsolve(row, cols, pie, na):if row == n:
res.append(board[:])returnfor col inrange(n):if col notin cols and row+col notin pie and row-col notin na:
board[row]='.'* col +'Q'+'.'*(n - col -1)
solve(row +1, cols |{col}, pie |{row+col}, na |{row-col})
res =[]
board =['.'* n for _ inrange(n)]
solve(0,set(),set(),set())return res
题目:按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
classSolution:defcanJump(self, nums: List[int])->bool:
max_reach =0for i inrange(len(nums)):if i > max_reach:returnFalse
max_reach =max(max_reach, i + nums[i])returnTrue
from typing import List
classSolution:defjump(self, nums: List[int])->int:
n =len(nums)if n ==1:return0
cur_max_reach =0
next_max_reach =0
steps =0for i inrange(n-1):
next_max_reach =max(next_max_reach, i + nums[i])if i == cur_max_reach:
steps +=1
cur_max_reach = next_max_reach
if cur_max_reach < n-1:return-1return steps
classSolution:defreconstructQueue(self, people: List[List[int]])-> List[List[int]]:
people.sort(key=lambda x:(-x[0], x[1]))
result =[]for p in people:
result.insert(p[1], p)return result
解释: 该题可以使用贪心的思维来做,首先对人员列表进行排序,排序规则是先按身高降序排列,如果身高相同,则按照在队列中的位置升序排列。这样排序的目的是为了确保在构建队列时,先排列身高较高的人,并且按照其在队列中的位置插入,使得身高较矮的人能够正确地站在他们前面,同时不影响身高较高的人的位置。接下来,代码创建了一个空列表 result 作为结果队列。然后遍历排序后的人员列表 people,对于每个人的信息 p,使用 insert 方法将其插入到 result列表的 p[1] 位置。由于按照身高降序排列,因此身高较高的人会先被插入到 result 中,而身高相同的人则根据其在队列中的位置顺序插入。
一.数组一.二分查找def er_fen_cha_zhao(nums,target): left = 0 right = len(nums) - 1 while left <= right: mid = (left + right)//2 if nums[mid] == target: return mid elif nums[mid] < target: left = m