生成 SSH 密钥对

# 生成 Ed25519 密钥对(更先进)
ssh-keygen -t ed25519 -C "your_email@example.com"

# 生成 RSA 密钥对(兼容性好)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

公钥部署到远程服务器

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote_host

创建/激活虚拟环境

创建虚拟环境:

python3 -m venv .venv

激活虚拟环境:

source .venv/bin/activate 

Pip 基本命令

  • pip install: 安装包
  • pip uninstall: 卸载包
  • pip list: 列出已安装包
  • pip freeze: 列出已安装包及精确版本(适合生成requirements.txt,例如pip freeze > requirements.txtpip install -r requirements.txt
  • pip show: 查看某个包的元信息
  • pip check: 检测已安装包依赖是否有冲突
  • pip search: 在 PyPI 上搜索包
  • pip download: 仅下载包压缩文件到当前目录,不安装
  • pip wheel: 构建 wheel 包(生成.whl文件),用于离线安装

定长滑动窗口

模板

右指针向右遍历:
    元素进入窗口(增长均值/总和等)
    若窗口尺寸不足:
        右指针继续向右
    否则:
        若满足条件(使题目而定):
            更新答案
        左指针右移,元素离开窗口

例题一

Leetcode 643. 子数组最大平均数 I

class Solution:
    def findMaxAverage(self, nums: List[int], k: int) -> float:
        ans, aver = float("-inf"), 0
        for i in range(len(nums)):
            # right = i
            # right - left + 1 = k
            # left = i - k + 1
            aver += nums[i]
            if i < k - 1:
                continue
            else:
                ans = max(ans, aver)
                aver -= nums[i - k + 1]
        return ans / k

例题二

Leetcode 2090. 半径为 k 的子数组平均值

class Solution:
    def getAverages(self, nums: List[int], k: int) -> List[int]:
        n = len(nums)
        avgs = [-1] * n
        avg = 0
        for i in range(n):
            # right = i
            # right - left + 1 = 2 * k + 1
            # left = i - 2 * k
            avg += nums[i]
            if i - 2 * k < 0:
                continue
            else:
                avgs[i - k] = avg // (2 * k + 1)
                avg -= nums[i - 2 * k]
        return avgs

例题三

Leetcode 2461. 长度为 K 子数组中的最大和

class Solution:
    def maximumSubarraySum(self, nums: List[int], k: int) -> int:
        n = len(nums)
        ans = 0
        temp_sum = 0
        window = defaultdict(int)
        for i in range(n):
            temp_sum += nums[i]
            window[nums[i]] += 1
            if i - k + 1 < 0:
                continue
            else:
                if len(window) == k:
                    ans = max(ans, temp_sum)
                temp_sum -= nums[i - k + 1]
                window[nums[i - k + 1]] -= 1
                if window[nums[i - k + 1]] == 0:
                    del window[nums[i - k + 1]]
        return ans

不定长滑动窗口

模板

右指针向右遍历:
    右移左指针直到窗口满足条件:
        左侧元素离开窗口
    右侧元素进入窗口
    # 上面这步也可能出现在循环的最开始
    # 这里演示用集合的做法,先加再删会导致刚加被删
    更新答案

例题一

Leetcode 3. 无重复字符的最长子串

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        ans = left = 0
        # 哈希表写法
        # cnt = defaultdict(int)
        # for right, ch in enumerate(s):
        #     cnt[ch] += 1
        #     while cnt[ch] > 1:
        #         cnt[s[left]] -= 1
        #         left += 1

        # 哈希集合写法
        window = set()
        for right, ch in enumerate(s):
            # 要先删再加,不然刚加的字符会被删
            while ch in window:
                window.remove(s[left])
                left += 1
            window.add(ch)
            ans = max(ans, right - left + 1)
        return ans

例题二

Leetcode 3090. 每个字符最多出现两次的最长子字符串

class Solution:
    def maximumLengthSubstring(self, s: str) -> int:
        ans = left = 0
        cnt = defaultdict(int)
        for right, ch in enumerate(s):
            cnt[ch] += 1
            while cnt[ch] > 2:
                cnt[s[left]] -= 1
                left += 1
            ans = max(ans, right - left + 1)
        return ans

Leetcode 3202. 找出有效子序列的最大长度 II

from typing import List


class Solution:
    def maximumLength(self, nums: List[int], k: int) -> int:
        f = [[0] * k for _ in range(k)]
        for x in nums:
            x %= k
            for y, fxy in enumerate(f[x]):
                f[y][x] = fxy + 1
        return max(map(max, f))


print(Solution().maximumLength([1, 2, 3, 4, 5], 2))

声明mn列二维数组:matrix = [[0] * n for _ in range(m)]

函数map(function, iterable):第一个参数为应用于每个元素的函数,第二个参数为可迭代对象

枚举右、维护左

Leetcode 1512. 好数对的数目

class Solution:
    def numIdenticalPairs(self, nums: List[int]) -> int:
        ans = 0
        cnt = collections.defaultdict(int)
        for j, x in enumerate(nums):
            if x in cnt:
                ans += cnt[x]
            cnt[x] += 1
        return ans

Leetcode 2001. 可互换矩形的组数

class Solution:
    """
    方法一:枚举右维护左
        时间复杂度O(n)
        空间复杂度O(n)
    """

    def interchangeableRectangles(self, rectangles: List[List[int]]) -> int:
        ans = 0
        cnt = collections.defaultdict(int)
        for j, matrix in enumerate(rectangles):
            if matrix[0] / matrix[1] in cnt:
                ans += cnt[matrix[0] / matrix[1]]
            cnt[matrix[0] / matrix[1]] += 1
        return ans

Leetcode 1128. 等价多米诺骨牌对的数量

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        ans = 0
        cnt = collections.defaultdict(int)
        for j, x in enumerate(dominoes):
            # 列表list是不可哈希的,所以用元组tuple
            if (x[0], x[1]) in cnt:
                ans += cnt[(x[0], x[1])]
            if x[0] != x[1] and (x[1], x[0]) in cnt:
                ans += cnt[(x[1], x[0])]
            cnt[(x[0], x[1])] += 1
        return ans

上述很多例题都可以用组合数学技巧优化(求...共有几对),不再赘述。