算法刷题
注:留意等于号跟在哪、是否要加1、特殊情况(前几个情况)
参考:
https://github.com/csujedihy/lc-all-solutions
https://space.bilibili.com/478428905/video
codetop
206.反转链表
口诀:while中等号右边对应下一行等号左边
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre=None
cur=head #定义双指针
while cur:
tmp=cur.next #存储下一个点
cur.next=pre #两个节点间逆序
pre=cur #
cur=tmp # 两个节点往前移动,cur会在pre前一个节点
return pre
补充题4.快速排序
方法1:
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def partition(nums, start, end):
p = random.randrange(start, end + 1) # 注意这里+1
pv = nums[p]
nums[end], nums[p] = nums[p], nums[end]
mid = start
for i in range(start, end):
if nums[i] <= pv:
nums[i], nums[mid] = nums[mid], nums[i]
mid += 1
nums[mid], nums[end] = nums[end], nums[mid]
return mid
def quicksort(nums, start, end):
if end - start <= 0:
return # 注意这里什么也不return
mid = partition(nums, start, end)
quicksort(nums, start, mid - 1)
quicksort(nums, mid + 1, end)
quicksort(nums,0,len(nums)-1) # 注意这里-1
return nums
方法2:
两头找会更快,leetcode 中可以不 import random
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
import random #导入随机数函数库
def quicksort(nums,left,right):
flag=nums[random.randint(left,right)] #随机初始化哨兵位置
i,j=left,right #设定从左到右的指针i,从右到左的指针j
while i<=j:
while nums[i]<flag: i+=1 #i从左往右扫,找到大于等于flag的数。
while nums[j]>flag: j-=1 #j从右往左扫,找到小于等于flag的数。
if i<=j:
nums[i],nums[j]=nums[j],nums[i] #交换左右指针下标对应的数值
i+=1 #左指针继续往右走
j-=1 #右指针继续往左走
if i<right: quicksort(nums,i,right) #递归解决flag左边的低位数组的排序
if j>left: quicksort(nums,left,j) #递归解决flag右边的低位数组的排序
quicksort(nums,0,len(nums)-1) #函数入口,将整个数组的信息传入
return nums #返回修改后的nums
21.合并两个有序链表
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
if not list1: return list2 # 终止条件,直到两个链表都空
if not list2: return list1
if list1.val <= list2.val: # 递归调用
list1.next = self.mergeTwoLists(list1.next,list2) # 谁小了就谁.next,可以理解为list1后面的所有节点和list2全部接到list1.next后面
return list1 # 改变了list1后的顺序,所以返回list1
else:
list2.next = self.mergeTwoLists(list1,list2.next) # self.mergeTwoLists中的list1和list2的顺序不能翻了
return list2
53.最大子数组和
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
preSum = maxSum = nums[0]
for i in range(1, len(nums)): # 共需存储两个值
preSum = max(preSum + nums[i], nums[i]) # 当前连续子列是否要断开,可以拿[-2,1]简单理解,推广到更多项
maxSum = max(maxSum, preSum) # 历史最大与当前最大对比
return maxSum
415.字符串相加
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
res = ""
i, j, carry = len(num1) - 1, len(num2) - 1, 0
while i >= 0 or j >= 0:
n1 = int(num1[i]) if i >= 0 else 0
n2 = int(num2[j]) if j >= 0 else 0
tmp = n1 + n2 + carry
carry = tmp // 10
res = str(tmp % 10) + res
i, j = i - 1, j - 1
return "1" + res if carry else res
704.二分查找
class Solution:
def search(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
8.字符串转为整数
解法1:
class Solution(object):
def myAtoi(self, s):
"""
:type str: str
:rtype: int
"""
s = s.strip()
sign = 1
if not s:
return 0
if s[0] in ["+", "-"]:
if s[0] == "-":
sign = -1
s = s[1:]
ans = 0
for c in s:
if c.isdigit():
ans = ans * 10 + int(c)
else:
break
ans *= sign
if ans > 2147483647:
return 2147483647
if ans < -2147483648:
return -2147483648
return
解法二:
class Solution:
def myAtoi(self, s: str) -> int:
return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)
正则表达式:
^:匹配字符串开头
[\+\-]:代表一个+字符或-字符
?:前面一个字符可有可无
\d:一个数字
+:前面一个字符的一个或多个
\D:一个非数字字符
*:前面一个字符的0个或多个
3.无重复字符串的最长子串
滑动窗口
def lengthOfLongestSubstring(self, s):
d = {}
start = 0
ans = 0
for i, c in enumerate(s):
if c in d:
start = max(start, d[c] + 1)
d[c] = i
ans = max(ans, i - start + 1)
return ans
215.数组中的第K个最大元素
方法1:
import random
class Solution(object):
def findKthLargest(self, nums, k):
"""
:type A: List[int]
:type k: int
:rtype: int
"""
def quickselect(start, end, nums, k):
if start == end:
return nums[start]
mid = partition(start, end, nums)
if mid == k:
return nums[mid]
elif k > mid:
return quickselect(mid + 1, end, nums, k)
else:
return quickselect(start, mid - 1, nums, k)
def partition(start, end, nums):
p = random.randrange(start, end + 1)
pv = nums[p]
nums[end], nums[p] = nums[p], nums[end]
mid = start
for i in range(start, end):
if nums[i] >= pv: # 左侧大
nums[i], nums[mid] = nums[mid], nums[i]
mid += 1
nums[mid], nums[end] = nums[end], nums[mid]
return mid
ret = quickselect(0, len(nums) - 1, nums, k - 1)
return ret
方法2:
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
q=[]
for i in nums:
heappush(q,i)
if len(q)> k:
heappop(q)
return q[0]
470.用 Rand7() 实现 Rand10()
套路1:(randX() - 1) * Y + randY() 可以生成1~X*Y的随机数(题目rand7可以生成 1~49的随机数)
套路2:randm() = randn() % m + 1, n > m,且n%m = 0(题目的rand10可以用rand40生成)
套路3:拒绝采样(1~49的随机数丢弃40以上的数就等价于rand40)
class Solution:
def rand10(self):
"""
:rtype: int
"""
while True:
tmp = (rand7()-1)*7+rand7()
if tmp <=40:
return tmp%10+1
234.回文链表
本质上是判断是否对称,步骤:1.找中点2.中点后逆序3.判断是否一致
逆序记忆方法:while中间–上一行的右边等于下一行的左边
参考:https://www.youtube.com/watch?v=GTKm1PrYjwo&ab_channel=%E8%B4%BE%E8%80%83%E5%8D%9A
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
def reverseList(root):
pre = None
cur = root
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
newHead = reverseList(slow)
p1 = head
p2 = newHead
while p1 and p2:
if p1.val != p2.val:
return False
p1 = p1.next
p2 = p2.next
return True
1.两数之和
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
d = {}
for i, num in enumerate(nums):
if target - num in d:
return [d[target - num], i]
d[num] = i
# no special case handling because it's assumed that it has only one solution
70.爬楼梯
斐波那契数列,可以分解为(n-2的结果+2)和(n-1的结果+1)
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n <= 1:
return 1
first, second = 1, 1
for i in range(2, n + 1):
third = first + second
first = second
second = third
return second
141.环形链表
若是链表无环,那么 fast 指针会先指向 Null。若是链表有环,fast 和 slow 迟早会在环中相遇。
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
fast = slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if slow == fast:
return True
return False
153.寻找旋转排序数组中的最小值
由于数组不包含重复元素,并且只要当前的区间长度不为1,pivot 就不会与 high 重合;而如果当前的区间长度为 1,这说明我们已经可以结束二分查找了。因此不会存在 num[pivot]=num[high]的情况
class Solution(object):
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
low, high = 0, len(nums) - 1
while low < high:
pivot = low + (high - low) // 2
if nums[pivot] < nums[high]:
high = pivot
else:
low = pivot + 1
return nums[low]
20.有效括号
方法1:
class Solution:
def isValid(self, s: str) -> bool:
stack=[]
hashmap={'(':')','[':']','{':'}'}
#如果个数是基数,直接false
if len(s) % 2 == 1:
return False
for i in s:
if i in hashmap: #如果是左括号,则加入栈
stack.append(i)
elif stack and hashmap[stack[-1]] == i:
stack.pop() #如果是右括号,且栈非空,且等于栈末位的左括号对应的右括号,则在栈中删除左括号
else:
return False
return len(stack) == 0 #有效的话此时栈为空
方法2:
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
stack = []
d = ["()", "[]", "{}"]
for i in range(0, len(s)):
stack.append(s[i])
if len(stack) >= 2 and stack[-2] + stack[-1] in d:
stack.pop()
stack.pop()
return len(stack) == 0
300.最长递增子序列
方法1:动态规划,视频参考https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/shi-pin-tu-jie-zui-chang-shang-sheng-zi-xu-lie-by-/
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if nums == []:
return 0
cell = [1]
for i in range(1,len(nums)):
cell.append(1)
for j in range(i):
if(nums[j] < nums[i]):
cell[i] = max(cell[i], cell[j]+1)
return max(cell)
方法2:单调栈
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
tail = []
for num in nums:
idx = bisect.bisect_left(tail, num)
if idx == len(tail):
tail.append(num)
else:
tail[idx] = num
return len(tail)
补充:输出子序列
链接:https://www.nowcoder.com/questionTerminal/9cf027bf54714ad889d4f30ff0ae5481?f=discussion
来源:牛客网
class Solution:
def LIS(self , arr ):
# write code here
# 贪心 + 二分
if len(arr) < 2:
return arr
ansVec = [arr[0]] # 记录以某一元素结尾的最长递增子序列,初始化为数组第一位元素
maxLen = [1] # 记录下标i处最长递增子序列的长度,初始化为[1](下标0此时只有一个数字,长度为1)
for num in arr[1:]:
if num > ansVec[-1]:
ansVec.append(num) # 更新以num为结尾元素的最长递增子序列
maxLen.append(len(ansVec)) # 同时更新此时最长递增子序列的长度
else:
# 二分查找第一个比num大的数字,替换
# 此时以该元素为结尾的最长递增子序列的长度为其在ansVec中的下标+1
left, right = 0, len(ansVec)-1
while left < right:
mid = (left + right) // 2
if ansVec[mid] < num:
left = mid+1
elif ansVec[mid] == num:
left = mid
break
else:
if ansVec[mid-1] < num:
left = mid
break
else:
right = mid-1
ansVec[left] = num
maxLen.append(left+1)
# ansVec不一定是最后结果,求解按字典序最小的结果
# 此时我们知道最长长度为ansLen,从后向前遍历maxLen,
# 遇到第一个maxLen[i]==ansLen的下标i处元素arr[i]即为所求,
# 例:
# [1,2,8,6,4] -> maxLen [1,2,3,3,3] -> ansLen=3
# [1,2,8] -> [1,2,6] -> [1,2,4] 长度一致的答案,字典序越小越靠后
ansLen = len(ansVec)
for i in range(len(arr)-1, -1, -1):
if maxLen[i] == ansLen:
ansVec[ansLen-1] = arr[i]
ansLen -= 1
return ansVec
4.寻找两个正序数组的中位数
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
n1 = len(nums1)
n2 = len(nums2)
if n1 > n2:
return self.findMedianSortedArrays(nums2,nums1) # 确保分割线左右两边都有元素,如果首先是长的,可能只在长的中间有分割线就ok
k = (n1 + n2 + 1)//2 # 不论奇偶,分割线左边元素个数满足条件
left = 0
right = n1
while left < right :
m1 = left +(right - left)//2 # 二分查找
m2 = k - m1
if nums1[m1] < nums2[m2-1]: # 交叉小于等于,即分割线左侧的小于分割线右侧的
left = m1 + 1
else:
right = m1
m1 = left
m2 = k - m1
c1 = max(nums1[m1-1] if m1 > 0 else float("-inf"), nums2[m2-1] if m2 > 0 else float("-inf") )
if (n1 + n2) % 2 == 1:
return c1
c2 = min(nums1[m1] if m1 < n1 else float("inf"), nums2[m2] if m2 <n2 else float("inf"))
return (c1 + c2) / 2
5.最长回文子串
中心扩散
class Solution:
def longestPalindrome(self, s: str) -> str:
res, n = "", len(s)
for i in range(n):
l = r = i # 中心是奇数
while l >= 0 and r < n and s[l] == s[r]:
l -= 1
r += 1
if r - l - 1 > len(res): # 多减了,r-(l+1)
res = s[l+1:r] # 这边同样由于多减了两遍都取不到
l, r = i, i + 1 # 中心是偶数
while l >= 0 and r < n and s[l] == s[r]:
l -= 1
r += 1
if r - l - 1 > len(res):
res = s[l+1:r]
return res
补充题6.堆排序
参考:https://zhuanlan.zhihu.com/p/151720319
def maxHepify(arr, i, end): # 大顶堆
j = 2*i + 1 # j为i的左子节点【建堆时下标0表示堆顶】
while j <= end: # 自上而下进行调整
if j+1 <= end and arr[j+1] > arr[j]: # i的左右子节点分别为j和j+1
j += 1 # 取两者之间的较大者
if arr[i] < arr[j]: # 若i指示的元素小于其子节点中的较大者
arr[i], arr[j] = arr[j], arr[i] # 交换i和j的元素,并继续往下判断
i = j # 往下走:i调整为其子节点j
j = 2*i + 1 # j调整为i的左子节点
else: # 否则,结束调整
break
n = len(nums)
# 建堆【大顶堆】堆初始化,从下往上
for i in range((n-1)//2, -1, -1): # 从第一个非叶子节点(n-1)//2开始依次往上进行建堆的调整
maxHepify(nums, i, n-1)
# 排序:依次将堆顶元素(当前最大值)放置到尾部,并调整堆
for j in range(n-1, -1, -1):
nums[0], nums[j] = nums[j], nums[0] # 堆顶元素(当前最大值)放置到尾部j
maxHepify(nums, 0, j-1) # j-1变成尾部,并从堆顶0开始调整堆,从上往下
return nums
15.三数之和
排序+双指针+特殊情况考虑
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
nums.sort()
for i in range(0, len(nums)):
if i > 0 and nums[i] == nums[i - 1]:
continue
target = 0 - nums[i]
start, end = i + 1, len(nums) - 1
while start < end:
if nums[start] + nums[end] > target:
end -= 1
elif nums[start] + nums[end] < target:
start += 1
else:
res.append((nums[i], nums[start], nums[end])) # 注意两个括号
end -= 1
start += 1
while start < end and nums[end] == nums[end + 1]: # 注意==
end -= 1
while start < end and nums[start] == nums[start - 1]:
start += 1
return res
384.打乱数组
洗牌算法:等概率选择每个位置应该填哪个数。
具体来说,我们先在0 ~ n-1中随机选一个坐标,将它作为第一个,和第一个交换位置;(每个数被选到的概率是1/n);剩下的n-1个数里,继续随机一个1 ~ n-1的坐标,将它作为第二个,和第二个交换位置(每个数被选到的概率为第一次没被选到且第二次被选到 ((n-1)/n) * (1/(n-1));以此类推。每个数填到每个位置是等概率的,都是1/n
class Solution:
def __init__(self, nums: List[int]):
self.nums = nums
def reset(self) -> List[int]:
return self.nums
def shuffle(self) -> List[int]:
self.temp = list(self.nums)
for i in range(len(self.nums)):
idx = random.randint(i, len(self.nums) - 1)
self.temp[i], self.temp[idx] = self.temp[idx], self.temp[i]
return self.temp
####### Your Solution object will be instantiated and called as such:
####### obj = Solution(nums)
####### param_1 = obj.reset()
####### param_2 = obj.shuffle()
226.翻转二叉树
递归
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return root
left = self.invertTree(root.left)
right = self.invertTree(root.right)
root.left,root.right=right,left
return root
347.前 K 个高频元素
堆排序
from collections import Counter
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
q=[]
for num,freq in Counter(nums).items():
if len(q)==k:
heappushpop(q,(freq,num)) # 注意这里要和for的时候顺序反一下
else:
heappush(q,(freq,num))
return [x[1] for x in q]
451.根据字符出现频率排序
class Solution:
def frequencySort(self, s: str) -> str:
Map = Counter(s)
ans = ''
for char, num in sorted(list(Map.items()), key = lambda x: -x[1]):
ans += char * num
return ans
1452.收藏清单
class Solution:
def peopleIndexes(self, f: List[List[str]]) -> List[int]:
ans = []
f = [set(x) for x in f]
for i,x in enumerate(f):
flag = 0
for j, y in enumerate(f):
if i==j: continue
if x&y==x:
flag = 1
break
if flag==0:
ans.append(i)
return ans
25.K 个一组翻转链表
class Solution:
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
def rev(a,b): # 指定区间反转,到b结束,注意这里是两个输入
pre=None
cur=a
while cur!=b: # b节点只在这里用了一次
tmp=cur.next
cur.next=pre
pre=cur
cur=tmp
return pre
a=b=head # 初始化头结点
for i in range(k): # 找到k节点之后的节点
if not b:
return head
b=b.next
n=rev(a,b) # 这个时候a在尾部,反转a-b区间的k个节点
a.next=self.reverseKGroup(b,k) # 递归更新尾节点的指针
return n
102.二叉树的层序遍历
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if root == None:
return []
res = []
queue = [root]
while queue:
res.append([node.val for node in queue])
# 存储当前层的孩子节点列表
childNodes = []
for node in queue:
# 若节点存在左孩子,入队
if node.left:
childNodes.append(node.left)
# 若节点存在右孩子,入队
if node.right:
childNodes.append(node.right)
# 更新队列为下一层的节点,继续遍历
queue = childNodes
return res
103.二叉树的锯齿形层序遍历
方法1:参考102针对奇偶使用逆序
class Solution:
def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
res = []
queue = [root]
f=0 # 多出
while queue:
if f%2==0: #
res.append([node.val for node in queue])
else: #
res.append([node.val for node in queue[::-1]]) # 多出
childNodes = []
for node in queue:
if node.left:
childNodes.append(node.left)
if node.right:
childNodes.append(node.right)
queue = childNodes
f+=1 # 多出
return res
方法2:双端队列
class Solution:
def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:return []
q = collections.deque([root])
f = True
ans = []
while q:
tmp = collections.deque([]) # 用一个双端队列来存结果
for _ in range(len(q)):
n = q.popleft()
if f: tmp.append(n.val) # 正向存结果
else: tmp.appendleft(n.val) # 反向存结果
if n.left:q.append(n.left)
if n.right:q.append(n.right)
f = not f # 标志位反转
ans.append(list(tmp))
return ans
121.买卖股票的最佳时间
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if not prices:
return 0
ans=0
pre=prices[0]
for i in range(1,len(prices)): #注意是range(1,len())
pre=min(pre,prices[i])
ans=max(ans,prices[i]-pre)
return ans
160.相交链表
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if not headA or not headB:
return None
pa=headA
pb=headB
while pa != pb:
pa = headB if not pa else pa.next
pb = headA if not pb else pb.next
return pa
236.二叉树的最近公共祖先
注意最近公共祖先的定义,且二叉树问题一般都可以通过递归解决
class Solution:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if not root or root == p or root == q: return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if not left and not right: return # 1. 可以合并到 3 / 4 里
if not left: return right # 3.
if not right: return left # 4.
return root # 2. if left and right
88.合并两个有序数组:逆向双指针
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
p1, p2 = m - 1, n - 1
tail = m + n - 1
while p1 >= 0 or p2 >= 0:
if p1 == -1:
nums1[tail] = nums2[p2]
p2 -= 1
elif p2 == -1:
nums1[tail] = nums1[p1]
p1 -= 1
elif nums1[p1] > nums2[p2]:
nums1[tail] = nums1[p1]
p1 -= 1
else:
nums1[tail] = nums2[p2]
p2 -= 1
tail -= 1
33.搜索旋转排序数组:
可以遍历,但为了提高效率用二分法(该题条件下,肯定有一边是有序的)
class Solution(object):
def search(self, nums, target):
if not nums:
return -1
left = 0
right = len(nums) - 1
while left <= right:
mid = (right + left) // 2
if nums[mid] == target:
return mid
if nums[mid] >= nums[left]:
if nums[left] <= target <= nums[mid]:
right = mid - 1
else:
left = mid + 1
else:
if nums[mid] <= target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1
23.合并k个升序链表
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
import heapq #调用堆
minHeap = []
for listi in lists:
while listi: #由于是链表所以要while和后续的.val和.next
heapq.heappush(minHeap, listi.val) #把listi中的数据逐个加到堆中,且由于是二叉树,仅从数来看不是严格递增的
listi = listi.next
dummy = ListNode(0) #构造虚节点
p = dummy
while minHeap: #heap是二叉树,用for i in minHeap,遍历得到的输出不全,所以要while,不断pop到没有值
p.next = ListNode(heapq.heappop(minHeap)) #依次弹出最小堆的数据,注意要加上listnode,否则是一个整数值
p = p.next
return dummy.next #return p.next为null,return p为6,所以只能是dummy
OJ在线编程常见输入输出练习场
import sys
for line in sys.stdin:
print(sum(map(int,line.split())))
n = int(input())
for i in range(n):
a,b = map(int, input().split())
print(a+b)
while True:
a, b = map(int, input().split())
if a == 0 and b == 0:
break
else:
print(a+b)
while True:
l = list(map(int, input().split()))
if l[0] > 0:
print(sum(l[1:]))
else:
break
n = int(input())
for i in range(n):
nums = list(map(int,input().split()))
print(sum(nums)-nums[0])
while True:
try:
nums = list(map(int,input().split()))
print(sum(nums)-nums[0])
except:
break
while True:
try:
nums = list(map(int,input().split()))
print(sum(nums))
except:
break
n = int(input())
string = input().split(' ')
print(" ".join(sorted(string)))
while True:
try:
a = input().split()
a.sort()
print(' '.join(a))
except:
break
while True:
try:
a = input().split(',')
a.sort()
print(','.join(a))
except:
break
a,b=map(int,input().split())
print(a+b)
import sys
if __name__ == "__main__":
# 读取第一行的n
n = int(sys.stdin.readline().strip())
ans = 0
for i in range(n):
# 读取每一行
line = sys.stdin.readline().strip()
# 把每一行的数字分隔后转化成int列表
values = list(map(int, line.split()))
for v in values:
ans += v
print(ans)
剑指Offer
09.用两个栈实现队列
class CQueue:
def __init__(self):
self.A, self.B = [], []
def appendTail(self, value: int) -> None:
self.A.append(value)
def deleteHead(self) -> int:
if self.B: return self.B.pop() #两个if的顺序和答案能否通过有关系
if not self.A: return -1
while self.A:
self.B.append(self.A.pop())
return self.B.pop()
30.包含min函数的栈
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.A,self.B=[],[]
def push(self, x: int) -> None:
self.A.append(x)
if not self.B or self.B[-1]>=x:
self.B.append(x)
def pop(self) -> None:
if self.A.pop()==self.B[-1]:
self.B.pop()
def top(self) -> int:
return self.A[-1]
def min(self) -> int:
return self.B[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()
06.从尾到头打印链表
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
stack = []
while head:
stack.append(head.val)
head = head.next
return stack[::-1]
24.反转链表
35.复杂链表的复制
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
if not head: return
dic = {}
# 3. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射
cur = head
while cur:
dic[cur] = Node(cur.val)
cur = cur.next
cur = head
# 4. 构建新节点的 next 和 random 指向
while cur:
dic[cur].next = dic.get(cur.next) # .get是根据键返回值
dic[cur].random = dic.get(cur.random)
cur = cur.next
# 5. 返回新链表的头节点
return dic[head]
05.替换空格
class Solution:
def replaceSpace(self, s: str) -> str:
res = []
for c in s:
if c == ' ': res.append("%20")
else: res.append(c)
return "".join(res)
58 - II.左旋转字符串
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
return s[n:] + s[:n]
03.数组中重复的数字
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key
class Solution:
def findRepeatNumber(self, nums: [int]) -> int:
dic = set()
for num in nums:
if num in dic: return num
dic.add(num)
return -1
53 - I.在排序数组中查找数字 I
排序数组中的搜索问题,首先想到 二分法 解决,// 为向下取整除法
class Solution:
def search(self, nums: [int], target: int) -> int:
def helper(tar):
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] <= tar: i = m + 1
else: j = m - 1
return i # 这里j最后会-1,所以返回i
return helper(target) - helper(target - 1)
53 - II.0~n-1中缺失的数字
class Solution:
def missingNumber(self, nums: List[int]) -> int:
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] == m: i = m + 1
else: j = m - 1
return i
04.二维数组中的查找
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
i, j = len(matrix) - 1, 0
while i >= 0 and j <= len(matrix[0])-1:
if matrix[i][j] > target: i -= 1
elif matrix[i][j] < target: j += 1
else: return True
return False
50.第一个只出现一次的字符
class Solution:
def firstUniqChar(self, s: str) -> str:
dic = {}
for c in s:
dic[c] = not c in dic
for c in s:
if dic[c]: return c
return ' '
11.旋转数组的最小数字
class Solution:
def minArray(self, numbers: [int]) -> int:
i, j = 0, len(numbers) - 1
while i <= j:
m = (i + j) // 2
if numbers[m] > numbers[j]: i = m + 1
elif numbers[m] < numbers[j]: j = m #注意这里没有-1
else: j -= 1 #这种情况-1
return numbers[i]
32 - I.从上到下打印二叉树
栈先入后出,队列先入先出
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
if not root: return []
res, queue = [], collections.deque()
queue.append(root) #是一个整体
while queue:
node = queue.popleft()
res.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
return res
32 - II.从上到下打印二叉树 II
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root: return []
res, queue = [], collections.deque()
queue.append(root)
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
res.append(tmp)
return res
32 - III.从上到下打印二叉树 III
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root: return []
res, queue = [], collections.deque()
queue.append(root)
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
res.append(tmp[::-1] if len(res) % 2 else tmp)
return res
26.树的子结构
先找节点,然后再看是否一致
class Solution:
def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
def recur(A, B):
if not B: return True
if not A or A.val != B.val: return False
return recur(A.left, B.left) and recur(A.right, B.right)
return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))
27.二叉树的镜像
class Solution:
def mirrorTree(self, root: TreeNode) -> TreeNode:
if not root: return
root.left, root.right = self.mirrorTree(root.right), self.mirrorTree(root.left)
return root
28.对称的二叉树
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
def recur(L, R):
if not L and not R: return True
if not L or not R or L.val != R.val: return False
return recur(L.left, R.right) and recur(L.right, R.left)
return recur(root.left, root.right) if root else True
10- I.斐波那契数列
class Solution:
def fib(self, n: int) -> int:
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a % 1000000007
10- II.青蛙跳台阶问题
class Solution:
def numWays(self, n: int) -> int:
a, b = 1, 1
for _ in range(n):
a, b = b, a + b
return a % 1000000007
63.股票的最大利润
class Solution:
def maxProfit(self, prices: List[int]) -> int:
cost, profit = float("+inf"), 0
for price in prices:
cost = min(cost, price)
profit = max(profit, price - cost)
return profit
60.n个骰子的点数
class Solution:
def dicesProbability(self, n: int) -> List[float]:
dp = [1 / 6] * 6
for i in range(2, n + 1):
tmp = [0] * (5 * i + 1)
for j in range(len(dp)):
for k in range(6):
tmp[j + k] += dp[j] / 6
dp = tmp
return dp