{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 编程机考笔记" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 常用代码段\n", "\n", "- [python算法常用内置库](https://segmentfault.com/a/1190000037505191)\n", "\n", "### 列表相关" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 列表推导式语法: [output_expression for out_exp in input_list if expression]\n", "# 这两种写法一个是两层的遍历, 一个是并行遍历\n", "a = [x*y for x in range(1,5) if x > 2 for y in range(1,4) if y < 3]\n", "a = [[i, j] for i, j in zip('1234', 'abcd')]\n", "\n", "# zip拼接\n", "l = list(zip(l1, l2, l3)) # 可以拼一组列表\n", "\n", "# zip纵向解列表\n", "l = [[i, j, k] for i, j, k in zip('1234', 'abcd', 'abcd')]\n", "a, b, c = zip(*l)\n", "# 一维的话也可以直接解 (这样解出来可变长参数始终会是列表, 不管有没有内容)\n", "l = [1, 2, 3, 4, 5]\n", "start, *middle, end = l\n", "\n", "# 并行遍历一组可迭代对象\n", "letters = ['a', 'b', 'c']\n", "numbers = [0, 1, 2]\n", "operators = ['*', '/', '+']\n", "for l, n, o in zip(letters, numbers, operators):\n", " print(f'{l}{n}{o}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 字符串相关\n", "\n", "[fstring官方文档](https://docs.python.org/zh-cn/3/tutorial/inputoutput.html#formatted-string-literals)\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 删除字符串中所有指定字符\n", "s = s.replace('a', '')\n", "# 获得词频\n", "from collections import Counter\n", "c = Counter(s) # 可以类似字典地访问" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 字典相关" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# zip拼接\n", "d = dict(zip(keys_l, values_l)) # 可以拼出字典\n", "\n", "# 带默认值的字典\n", "import collections\n", "list_dict = collections.defaultdict(list) # list类型的默认值为[]\n", "int_dict = collections.defaultdict(int) # int类型的默认值为0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 输入输出\n", "\n", "### stdin/stdout\n", "\n", "❗进来都是`str`\n", "\n", "#### 针对单组输入\n", "\n", "❗`sys.stdin`不会去掉输出末尾的`\\n`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import sys\n", "data = [s.strip() for s in sys.stdin.readlines()]\n", "\n", "for d in data:\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 针对多组输入\n", "\n", "❗`input()`自带去掉末尾`\\n`功能" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "while True:\n", " try:\n", " s = input()\n", " except:\n", " break" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 易错点\n", "\n", "1. 给函数传参列表时可以进来先深拷贝一下:`l = l[:]`\n", "2. 删除列表元素时可能越界, 要么在遍历外一次`l.pop()`删完, 要么用列表推导式\n", "2. 为了应对可能为空列表的输入, 输出列表最好只赋`[]`初值, 在遍历时不截取而是用整个输入, 这样空列表的话会直接跳出遍历." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 算法\n", "\n", "### 排序\n", "\n", "- `sorted(iterable, /, *, key=None, reverse=False)`**iterable**处放个可迭代对象, **key**处放自定义函数来选取比较的参数, 可以是个参数元组\n", "- `sorted()`和`list.sort()`对多维列表默认使用第一维排序, 用`key=lambda i: i[idx]`指定维度\n", "- `zip()`可用来并行排序, `l = sorted(zip(l1, l2))`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# list\n", "l.sort()\n", "l = sorted(l)\n", "# dict\n", "# 按键排序\n", "d = sorted(d.items(), key=lambda i: i[0])\n", "# 按值排序\n", "d = sorted(d.items(), key=lambda i: i[1])\n", "# 字典列表\n", "d_l = [\n", " { \"name\" : \"Taobao\", \"age\" : 100},\n", " { \"name\" : \"Runoob\", \"age\" : 7 },\n", " { \"name\" : \"Google\", \"age\" : 100 },\n", " { \"name\" : \"Wiki\" , \"age\" : 200 }\n", "]\n", "# 按age排序\n", "d_l = sorted(d_l, key = lambda i: i['age'])\n", "# 按age, name排序\n", "d_l = sorted(d_l, key = lambda i: (i['age'], i['name']))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 排列组合" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import itertools # TODO: 这个库要进一步研究\n", "arr = [1, 2, 3]\n", "list(itertools.permutations(arr, 3)) # 排列Pn3\n", "list(itertools.combinations(arr, 2)) # 组合Cn2\n", "list(itertools.product(arr)) # TODO: 考虑先后顺序有放回地抽取" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 手动实现全排列\n", "\n", "##### 普通递归\n", "\n", "- 确定第一位, 移动指针, 对n-1位遍历\n", "- 确定第二位, 移动指针, 对n-2位遍历\n", "- ...\n", "- 直到只剩一位, 返回值\n", "\n", "❗ python递归默认最大深度为**1000**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def permutations(arr: list, position: int, end: int) -> None:\n", " if position == end: # 基本条件\n", " print(arr)\n", " else:\n", " arr = arr.copy() # 避免对原列表进行操作\n", " for index in range(position, end):\n", " arr[index], arr[position] = arr[position], arr[index]\n", " permutations(arr, position + 1, end)\n", "\n", "arr = [1, 2, 3]\n", "permutations(arr, 0, len(arr))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### 回溯法\n", "\n", "深搜, 返回时回溯\n", "\n", "[leetcode详细题解](https://leetcode-cn.com/problems/permutations/solution/quan-pai-lie-by-leetcode-solution-2/)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]]\n" ] } ], "source": [ "def permute(nums):\n", " \"\"\"\n", " :type nums: List[int]\n", " :rtype: List[List[int]]\n", " \"\"\"\n", " def backtrack(first=0):\n", " # 所有数都填完了\n", " if first == n:\n", " res.append(nums[:])\n", " for i in range(first, n):\n", " # 动态维护数组\n", " nums[first], nums[i] = nums[i], nums[first]\n", " # 继续递归填下一个数\n", " backtrack(first + 1)\n", " # 撤销操作\n", " nums[first], nums[i] = nums[i], nums[first]\n", "\n", " n = len(nums)\n", " res = []\n", " backtrack()\n", " return res\n", "\n", "arr = [1, 2, 3]\n", "print(permute(arr))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 二分查找" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n", "[1, 6, 3, 3.5, 4, 5]\n" ] } ], "source": [ "import bisect\n", "\n", "l = [1, 6, 3, 4, 5]\n", "item = 3.5\n", "print(bisect.bisect_left(l, item)) # TODO: 差值最小?\n", "print(bisect.bisect_right(l, item)) # TODO: 差值最小?\n", "l.insert(bisect.bisect(l, item), item)\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 深度优先搜索 (DFS)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 广度优先搜索 (BFS)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 滑动窗口\n", "\n", "#### 无重复最长子字符串" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "max_len = 0\n", "start, end = 0, 0" ] } ], "metadata": { "interpreter": { "hash": "767d51c1340bd893661ea55ea3124f6de3c7a262a8b4abca0554b478b1e2ff90" }, "kernelspec": { "display_name": "Python 3.10.2 64-bit", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.2" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }