基于ESP32的AIS转WiFi转换器:实现NMEA 0183数据无线传输
2026/5/26 0:26:11
我们现在准备刷题了,时间紧、任务重,希望快速上手。只学对刷题最有用的 20% Python 知识,先能写题、跑通、过样例,再逐步变强。
首先我们刷题前要知道的
collections / heapq / bisect / functools)和固定模板(双指针/栈/队列/BFS/二分/回溯/DP)就能解决:然后开始我们的新手LeetCode刷题入门指南。
int,float,str,list,dict,set,tupleif/else,for,whiledef, 参数与返回值len,sum,max,min,sorted,enumerate,zipsplit,join,strip,replacecollections,math| 模块 | 要掌握的知识 | 关键语法 | 举例 | 对刷题的帮助 |
|---|---|---|---|---|
| 变量与类型 | 不需要声明类型,直接赋值即可 | a = 10、b = "hi" | x = 3.14、name = "Alice" | 编程更快,不用int/char定义 |
| 输入输出 | input()读入字符串;print()输出 | s = input();print(x) | print("答案:", ans) | 用来调试或输出结果 |
| 注释 | 单行用#,多行用三引号 | # 这是注释 | '''多行注释''' | 写题解说明、调试 |
| 缩进 | 控制代码块,无大括号{} | if x>0:\n print(x) | – | 必须保持统一(常为4空格) |
| 类型 | 定义方式 | 常用操作 | 示例 | 刷题用途 |
|---|---|---|---|---|
| int / float | a = 10;b = 3.14 | + - * / // % | 5 // 2 -> 2(整除) | 计数、取模、循环控制 |
| str(字符串) | 'abc'或"abc" | s[i]取字符;len(s)长度 | "abc"[1] -> 'b' | 处理文本、回文串 |
| list(列表) | [1, 2, 3] | append(x),pop(),len(),切片a[1:3] | nums = [1,2,3]; nums.append(4) | 最常用容器! |
| dict(字典/哈希表) | {"a":1, "b":2} | d["a"]取值;d.keys();d.get("x",0) | cnt = {"a":1};cnt["a"]+=1 | 高频题结构(Two Sum) |
| set(集合) | {1,2,3} | add(x),remove(x),in判断 | s = {1,2}; 3 in s -> False | 去重、判断是否出现 |
| tuple(元组) | (1,2,3) | 不可修改,用于返回多个值 | return (x, y) | 函数多返回值、排序key |
| 结构 | Python写法 | 示例 | 说明 |
|---|---|---|---|
| if / elif / else | if 条件: | if x>0:\n print("正")\nelif x==0:\n print("零")\nelse:\n print("负") | 注意冒号:和缩进 |
| for循环 | for 变量 in 序列: | for i in range(5): print(i) | range(n)表示0到n-1 |
| while循环 | while 条件: | while n>0:\n n-=1 | 同C语言逻辑 |
| break / continue | 同C语言 | if i==3: break | 控制循环流 |
| for…else(特殊) | 循环正常结束后执行else | 搜索时常用 | 不掌握也行,了解即可 |
| 内容 | 语法 | 示例 | 说明 |
|---|---|---|---|
| 定义函数 | def 函数名(参数): | def add(a,b): return a+b | 没有类型声明 |
| 返回值 | return | return x, y | 可返回多个值 |
| 默认参数 | def f(x=0): ... | f()=f(0) | 常用在递归中 |
| 匿名函数 | lambda x: x+1 | map(lambda x:x+1, arr) | 列表排序、函数式操作 |
Python 传参基本就是“传对象的引用”。
关键是:
int/str/tuple不可变对象:函数里改它,外面不变。
list/dict/set可变对象:函数里改内容,外面会变。
常见错误1:不要用可变对象当默认参数(可变对象默认参数正确写法)
❌ 错误做法:
deff(path=[]):path.append(1)returnpathpath=[]在函数定义时初始化一次,之后每次函数调用都使用这个初始生成的同一个列表。✅ 正确做法:
deff(path=None):ifpathisNone:path=[]path.append(1)returnpathNone作为默认值,每次函数调用时都会创建一个新的空列表。常见错误2:回溯/DFS里要用path[:]等浅拷贝
因为path是 list(可变),你要“存档一份当时的快照”,就得拷贝:
ans=[]path=[]defdfs(i):ifi==3:ans.append(path[:])# 关键:拷贝一份returnpath.append(i)dfs(i+1)path.pop()dfs(0)print(ans)(这里可以看一下我们上一篇的帖子,了解一下常见的直接赋值,浅拷贝,深拷贝的错误和理解。)
| 目的 | 写法 | 例子 |
|---|---|---|
| 返回单个值 | return value | return "ok" |
| 返回多个值 | return a, b, c | return q, r |
| 返回列表 | return [ ... ] | return [i, j] |
| 返回字典 | return { ... } | return {"a":1,"b":2} |
| 不返回/占位 | return或省略 | return(等价None) |
如果你的函数暂时不需要写什么内容,可以补充一个pass当占位符
pass语句:用于语法上需要语句但什么也不做的场景(如函数、类、循环的占位),例如:deftodo():pass# 暂时不写实现ifcondition:pass# 稍后处理| 功能 | 语法 | 示例 | 说明 |
|---|---|---|---|
| 创建列表 | [表达式 for 变量 in 序列] | [i*i for i in range(5)] → [0,1,4,9,16] | 简洁、常用 |
| 带条件 | [x for x in nums if x>0] | [x for x in [1,-2,3] if x>0] → [1,3] | 常用于过滤 |
💡刷题常见用法:
nums=[int(x)forxininput().split()](把输入的一行数字变成整型数组)
| 函数 | 用法 | 示例 | 常见用途 |
|---|---|---|---|
len() | 求长度 | len(nums) | 数组、字符串长度 |
sum() | 求和 | sum(nums) | 快速统计 |
max() / min() | 最大/最小 | max(nums) | |
sorted() | 排序 | sorted(nums, reverse=True) | |
enumerate() | 获取下标和值 | for i, val in enumerate(nums): | 常用于遍历 |
zip() | 打包多个序列 | for a,b in zip(nums1,nums2): | 同步遍历两个数组 |
any() | 任一为真 | any(x<0 for x in nums) | 条件判断 |
all() | 全部为真 | all(x>=0 for x in nums) | 条件判断 |
| 操作 | 用法 | 示例 | 说明 |
|---|---|---|---|
split() | 按空格拆分字符串 | "a b c".split()→['a','b','c'] | 输入解析 |
join() | 合并列表为字符串 | ",".join(['a','b'])→"a,b" | 输出格式化 |
strip() | 去掉首尾空白 | " abc ".strip()→"abc" | |
replace() | 替换子串 | "aba".replace('a','x')→"xbx" | |
| 切片 | s[l:r] | "abcd"[1:3]="bc" | 子串 |
| 库/工具 | 一句话核心功能(新手友好版) | 最简示例(可以直接抄) | 常用场景 |
|---|---|---|---|
math | 常用数学计算(平方根、向上取整、最大公约数等) | math.sqrt(x)math.ceil(x)math.gcd(a,b) | 数论、几何、计算题 |
collections.Counter | 统计列表元素出现次数 | cnt = Counter(nums) | 频次统计、词频分析 |
collections.defaultdict | 访问不存在的键时自动初始化默认值 | d = defaultdict(list)d[key].append(val) | 分组统计、邻接表 |
collections.deque | 双端队列:头尾都能快速增删 | q = deque([1,2])q.append(3); q.popleft() | BFS、滑动窗口 |
heapq | 最小堆:随时获取最小值 | heappush(h, x)min_val = heappop(h) | TopK、合并有序列表 |
bisect | 二分查找:在有序列表中找插入位置 | pos = bisect_left(arr, x) | 二分搜索边界 |
functools.lru_cache | 记忆化装饰器:缓存递归结果 | @lru_cache(maxsize=None) | 递归DP、记忆化搜索 |
目标:能分析时间复杂度、选择合适的数据结构解题。
目标:能看出题目属于哪一类,直接套模板。
a.sort()# 升序a.sort(reverse=True)# 降序a.sort(key=lambdax:x[1])# 按第2个元素排序(二维数组/区间)fromcollectionsimportdefaultdict cnt=defaultdict(int)forxinnums:cnt[x]+=1fromcollectionsimportdeque q=deque([start])whileq:cur=q.popleft()importheapq h=[]heapq.heappush(h,3)heapq.heappush(h,1)x=heapq.heappop(h)# 1(最小的先出来)frombisectimportbisect_left i=bisect_left([1,2,4,4,7],4)# i == 2fromfunctoolsimportlru_cache@lru_cache(None)deff(i):ifi<=1:return1returnf(i-1)+f(i-2)b=a[:]# 拷贝一份(避免一起变)# ans.append(path[:]) 也是同样道理classSolution:deftwoSum(self,nums,target):pos={}fori,xinenumerate(nums):y=target-xifyinpos:return[pos[y],i]pos[x]=ireturn[]classSolution:deftwoSumSorted(self,nums,target):l,r=0,len(nums)-1whilel<r:s=nums[l]+nums[r]ifs==target:return[l,r]elifs<target:l+=1else:r-=1return[-1,-1]classSolution:defminSubArrayLen(self,target,nums):n=len(nums)l=0s=0ans=float('inf')forrinrange(n):s+=nums[r]whiles>=target:ans=min(ans,r-l+1)s-=nums[l]l+=1return0ifans==float('inf')elseansclassSolution:defisValid(self,s:str)->bool:pair={')':'(',']':'[','}':'{'}st=[]forchins:ifchin"([{":st.append(ch)else:ifnotstorst[-1]!=pair.get(ch,'#'):returnFalsest.pop()returnnotstfromcollectionsimportdequeclassSolution:defbfs(self,start):q=deque([start])visited=set([start])whileq:cur=q.popleft()# 处理 curfornxtin[]:# 这里替换成邻居列表ifnxtnotinvisited:visited.add(nxt)q.append(nxt)classSolution:deflowerBound(self,nums,target):l,r=0,len(nums)# 注意 r = len(nums)whilel<r:mid=(l+r)//2ifnums[mid]>=target:r=midelse:l=mid+1returnlclassSolution:defsubsets(self,nums):ans=[]path=[]defdfs(i):ifi==len(nums):ans.append(path[:])# 拷贝快照return# 不选dfs(i+1)# 选path.append(nums[i])dfs(i+1)path.pop()dfs(0)returnansclassSolution:defclimbStairs(self,n:int)->int:ifn<=2:returnn a,b=1,2for_inrange(3,n+1):a,b=b,a+breturnbclassSolution:defyourMethod(self,...):# 1) 参数检查(可选)# 2) 初始化# 3) 主循环 / 递归# 4) 返回结果passclassSolution:defyourMethod(self,param1,param2):# 你的方法实现passdeftest_your_method():s=Solution()asserts.yourMethod(param1,param2)=="expected_value"if__name__=="__main__":test_your_method()print("All tests passed.")LeetCode 页面有「自定义测试用例」输入框,直接贴 JSON 风格输入即可。
例如 Two Sum:
输入:
[2,7,11,15] 9 ……本地使用断言测试时,把这些样例输入我们创建的方法入口中
classSolution:deftwoSum(self,nums,target):pos={}fori,xinenumerate(nums):y=target-xifyinpos:return[pos[y],i]pos[x]=ireturn[]deftest_two_sum():s=Solution()asserts.twoSum([2,7,11,15],9)==[0,1]asserts.twoSum([3,3],6)==[0,1]asserts.twoSum([-1,-2,-3,-4,-5],-8)==[2,4]if__name__=="__main__":test_two_sum()print("All tests passed.")口诀:空、单元素、极端、重复、负数/特殊字符
| 题型 | 必备样例 | 说明/目的 |
|---|---|---|
| 数组查找/哈希 | 正常用例;重复元素;负数;目标不存在/多解(看题目是否保证有解) | 覆盖哈希查找的关键分支 |
| 双指针/滑窗 | 已排序 & 未排序;窗口极小/极大;全不满足/全满足 | 检查左右边界更新是否正确 |
| 字符串 | 空串;单字符;大小写混合;含空格或标点;Unicode(了解即可) | 检验遍历与条件过滤 |
| 栈/队列 | 合法序列;非法但长度接近;嵌套深度很深 | 易错在出栈时机与匹配 |
| 二分 | 目标在头/尾;不存在;全相等;有重复的最左/最右 | 检查 mid & 边界收缩 |
| 动态规划 | n=0/1 的最小规模;最大规模;边界转移(如 0/负数) | 检验初值与转移式 |
| 链表 | 空链;单节点;环/无环(看题);头尾操作 | 指针移动与返回头结点 |
| 树 | 空树;单节点;只有左/右子树;完全/不完全 | 递归 base case 是否健壮 |