数据结构与算法之数组: LeetCode 17. 电话号码的字母组合 (Ts, Py, Go版)

手把手教你用Docker快速部署开源MES系统(附避坑指南) 本文提供了一份详细的实战指南,手把手教你使用Docker容器化技术快速部署开源MES系统。内容涵盖从环境准备、项目选型、数据库配置到应用服务器优化、前端部署及生产环境监控的全流程,并附有避坑指南,旨在帮助中小制造企业IT人员和开发者低成本、高效率地构建智能制造解决方案。 阅读详情

电话号码的字母组合

  • https://leetcode.cn/problems/letter-combinations-of-a-phone-number/

描述

  • 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

  • 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

    12(abc)3(def)
    4(ghi)5(jkl)6(mno)
    7(pqrs)8(tuv)9(wxyz)
    *0#

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

提示

  • 0 <= digits.length <= 4
  • digits[i] 是范围 [‘2’, ‘9’] 的一个数字

Typescript 版算法实现

1 )方案 1: 深度优先遍历

function letterCombinations(digits: string): string[] {
  // 对输入做处理,如果小于1返回空
  if (digits.length < 1) return []
  // 建立电话号码键盘字典映射
  const dict: string[] = ['', '', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz']
  // 如果只给了一个按键,直接把按键内容取出来并按单个字符分组
  if (digits.length < 2) return dict[digits].split('')
  // 把输入字符串按单字符分隔变成数组,234 => [2,3,4]
  const num: string[] = digits.split('')
  // 保存键盘映射后的字母内容,如 23 => ['abc','def']
  const code: string[] = []
  num.forEach(item => {
    if (!dict[item]) return
    code.push(dict[item])
  })
  // 这里arr可以是数组和字符串的集合
  const comb = (arr: any[]) => {
    // 临时变量用来保存前两个组合的结果
    const tmp: string[] = []
    // 最外层的循环是遍历第一个元素,里层的循环是遍历第二个元素
    for (let i = 0, ilen = arr[0].length; i < ilen; i++) {
      for (let j = 0, jlen = arr[1].length; j < jlen; j++) {
        tmp.push(`${arr[0][i]}${arr[1][j]}`)
      }
    }
    // 从数组中索引为0开始删除,一共删除2个元素,将arr数组的前两项用 tmp 数组替代
    arr.splice(0, 2, tmp)
    if (arr.length > 1) {
      comb(arr)
      // 这是递归后形成的最后一个结果数组进行返回,这个数组只有一个元素
      return arr[0]
    }
    return tmp
  }
  return comb(code)
};
  • 按照题目要求,可以任意输入符合要求的数值型字符串来获取最终的组合结果
  • 我们并不知道用户会输入多少字符,比如:2,3;2,3,4;2,3,4,5;2,3,4,5,6,…
  • 所以并不适合使用n层循环来暴力枚举,需要的是两两组合
  • 两两组合完事后,将前两个替换成最新的一个来与后面的一个再次进行两两组合
  • 直到最终只有一个数组的时候结束,这里用的递归的思路来处理的
  • 同时,我们字符串和数组都可以按下标来进行访问,这一点要注意
  • 这里一个重要的数组api是 splice,即这行:arr.splice(0, 2, tmp)
  • 这里arr是个any[]类型的数组,里面的数据结构是字符串和数组混合结构的数组
  • 这里考察的是组合关系
  • 这个dict字典的设计是比较合适的,前两个都是'', 为了和数字与下标的转换进行匹配
  • 但是重新审视这个算法,两个for循环嵌套,还是递归,这里时间复杂度较高
  • 时间复杂度为 O(N + N + N + log(N) * K * L^2)
    • 其中 N 为输入字符串长度,K 为有效按键数量,L 为按键平均长度
  • 空间复杂度为 O(N + N + K * L + log(N) * K * L)
    • 构建了 num 数组和 code 数组,它们各自的空间复杂度为 O(N)
    • 递归调用时,使用了 tmp 临时数组,其空间复杂度为 O(K * L),其中 K 为数组长度,L 为数组平均长度
    • 递归调用的层数为 log(N),每层都有一个 tmp 数组,因此总体递归的空间复杂度为 O(log(N) * K * L)

2)方案2: 回溯

// 定义 letterCombinations 方法,接收一个字符串参数 digits,返回一个字符串数组
function  letterCombinations(digits: string): string[] {
    // 如果 digits 为空字符串,直接返回空数组
    if (!digits) return [];
    // 定义电话号码对应的字母组合映射
    const phoneMap: { [key: string]: string } = {
        "2": "abc",
        "3": "def",
        "4": "ghi",
        "5": "jkl",
        "6": "mno",
        "7": "pqrs",
        "8": "tuv",
        "9": "wxyz",
    };
    // 定义回溯函数,接收一个索引参数
    const backtrack = (index: number): void => {
        // 如果索引等于 digits 的长度,将当前组合加入结果数组
        if (index === digits.length) {
            combinations.push(combination.join(''));
        } else {
            // 获取当前数字对应的字母组合
            const digit = digits[index];
            // 遍历当前数字对应的字母组合
            for (const letter of phoneMap[digit]) {
                // 将当前字母加入组合
                combination.push(letter);
                // 递归调用回溯函数,增加索引
                backtrack(index + 1);
                // 回溯,将最后加入的字母移除,尝试其他字母
                combination.pop();
            }
        }
    };

    // 初始化组合和结果数组
    const combination: string[] = [];
    const combinations: string[] = [];

    // 调用回溯函数,从索引 0 开始
    backtrack(0);
    // 返回最终的结果数组
    return combinations;
}
  • 使用哈希表存储每个数字对应的所有可能的字母,然后进行回溯操作
  • 回溯过程中维护一个字符串,表示已有的字母排列
  • 如果未遍历完电话号码的所有数字,则已有的字母排列是不完整的
  • 该字符串初始为空。每次取电话号码的一位数字
  • 从哈希表中获得该数字对应的所有可能的字母,并将其中的一个字母插入到已有的字母排列后面
  • 然后继续处理电话号码的后一位数字,直到处理完电话号码中的所有数字
  • 即得到一个完整的字母排列。然后进行回退操作,遍历其余的字母排列
  • 回溯算法用于寻找所有的可行解,如果发现一个解不可行,则会舍弃不可行的解
  • 在这道题中,由于每个数字对应的每个字母都可能进入字母组合,因此不存在不可行的解,直接穷举所有的解即可
  • 时间复杂度:O(3m×4n3^m × 4^n3m×4n)
  • 空间复杂度: O(m + n) 线性
  • m 是对应三个字母的数字个数,n 是对应四个字母的数字个数

3 )方案 3: 广度优先遍历

// 定义 letterCombinations 方法,接收一个字符串参数 digits,返回一个字符串数组
function letterCombinations(digits: string): string[] {
    // 如果 digits 为空字符串,直接返回空数组
    if (!digits) return [];
    // 定义电话号码对应的字母组合数组
    const phone: string[] = ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz'];
    // 初始化队列,将空字符串作为初始元素
    let queue: string[] = [''];
    // 遍历输入的数字字符串
    for (const digit of digits) {
        // 获取当前队列的长度
        const queueLength = queue.length;
        // 遍历当前队列中的元素
        for (let i = 0; i < queueLength; i++) {
            // 从队列中取出一个元素
            const tmp = queue.shift()!;
            // 遍历当前数字对应的字母组合, 这里字符串 2 的 Unicode 编码是 50, 减去后对应上述数组的索引
            for (const letter of phone[digit.charCodeAt(0) - 50]) {
                // 将当前元素和字母组合的每个字母拼接,然后加入队列
                queue.push(tmp + letter);
            }
        }
    }
    // 返回最终的结果数组
    return queue;
}
  • 使用队列,先将输入的 digits 中第一个数字对应的每一个字母入队
  • 然后将出队的元素与第二个数字对应的每一个字母组合后入队…直到遍历到 digits 的结尾
  • 最后队列中的元素就是所求结果
  • 总结下来就是:利用队列,从当前出发,逐步构造解
  • 时间复杂度:O(3m×4n3^m × 4^n3m×4n)
  • 空间复杂度:O(3m×4n3^m × 4^n3m×4n)
  • m 是对应三个字母的数字个数,n 是对应四个字母的数字个数

Python3 版算法实现

1 )方案1: 深度优先

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        # 对输入做处理,如果小于1返回空
        if len(digits) < 1:
            return []
        # 建立电话号码键盘字典映射
        dict = ['', '', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz']
        # 如果只给了一个按键,直接把按键内容取出来并按单个字符分组
        if len(digits) < 2:
            return list(dict[int(digits)])
        # 把输入字符串按单字符分隔变成数组,234 => [2,3,4]
        num = list(digits)
        # 保存键盘映射后的字母内容,如 23 => ['abc','def']
        code = []
        for item in num:
            if not dict[int(item)]:
                continue
            code.append(dict[int(item)])
        # 这里arr可以是数组和字符串的集合
        def comb(arr):
            # 临时变量用来保存前两个组合的结果
            tmp = []
            # 最外层的循环是遍历第一个元素,里层的循环是遍历第二个元素
            for i in range(len(arr[0])):
                for j in range(len(arr[1])):
                    tmp.append(arr[0][i] + arr[1][j])
            # 从数组中索引为0开始删除,一共删除2个元素,将arr数组的前两项用 tmp 数组替代
            arr.pop(0)
            arr.pop(0)
            arr.insert(0, tmp)
            if len(arr) > 1:
                comb(arr)
                # 这是递归后形成的最后一个结果数组进行返回,这个数组只有一个元素
                return arr[0]
            return tmp
        return comb(code)

2 )方案2: 回溯

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        # 如果 digits 为空字符串,直接返回空列表
        if not digits:
            return []

        # 定义电话号码对应的字母组合映射
        phone_map = {
            "2": "abc",
            "3": "def",
            "4": "ghi",
            "5": "jkl",
            "6": "mno",
            "7": "pqrs",
            "8": "tuv",
            "9": "wxyz",
        }

        # 定义回溯函数
        def backtrack(index, combination):
            # 如果索引等于 digits 的长度,将当前组合加入结果列表
            if index == len(digits):
                combinations.append("".join(combination))
            else:
                # 获取当前数字对应的字母组合
                digit = digits[index]
                # 遍历当前数字对应的字母组合
                for letter in phone_map[digit]:
                    # 将当前字母加入组合
                    combination.append(letter)
                    # 递归调用回溯函数,增加索引
                    backtrack(index + 1, combination)
                    # 回溯,将最后加入的字母移除,尝试其他字母
                    combination.pop()

        # 初始化组合和结果列表
        combination = []
        combinations = []

        # 调用回溯函数,从索引 0 开始
        backtrack(0, combination)
        # 返回最终的结果列表
        return combinations

3 )方案3: 广度优先

from collections import deque

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        # 如果 digits 为空字符串,直接返回空列表
        if not digits:
            return []
        # 定义电话号码对应的字母组合数组
        phone = ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz']
        # 初始化队列,将空字符串作为初始元素
        queue = deque([''])
        # 遍历输入的数字字符串
        for digit in digits:
            # 获取当前队列的长度
            queue_length = len(queue)
            # 遍历当前队列中的元素
            for _ in range(queue_length):
                # 从队列中取出一个元素
                tmp = queue.popleft()
                # 遍历当前数字对应的字母组合
                for letter in phone[ord(digit) - 50]:
                    # 将当前元素和字母组合的每个字母拼接,然后加入队列
                    queue.append(tmp + letter)
        # 返回最终的结果列表
        return list(queue)

Golang 版算法实现

1 )方案1: 深度优先

import (
	"strings"
)

func letterCombinations(digits string) []string {
	// 对输入做处理,如果小于1返回空
	if len(digits) < 1 {
		return []string{}
	}
	// 建立电话号码键盘字典映射
	dict := []string{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}

	var result []string // 最终结果集
	// 如果只给了一个按键,直接把按键内容取出来并按单个字符分组
	if len(digits) < 2 {
		return strings.Split(dict[digits[0]-'0'], "")
	}
	// 把输入字符串按单字符分隔变成数组,234 => [2,3,4]
	num := strings.Split(digits, "")
	// 保存键盘映射后的字母内容,如 23 => ['abc','def']
	code := [][]string{}
	for _, item := range num {
		if len(dict[item[0]-'0']) == 0 {
			continue
		}
		code = append(code, []string{dict[item[0]-'0']})
	}
	// 递归函数,用于生成字母组合
	var comb func(arr [][]string)
	comb = func(arr [][]string) {
		// 检查数组长度是否大于等于2
		if len(arr) < 2 {
			result = arr[0]
			return
		}
		// 临时变量用于保存前两个组合的结果
		tmp := []string{}
		// 遍历第一个元素的每个字母与第二个元素的每个字母的组合
		firstLen := len(arr[0])
		for _, item := range arr[0] {
			if firstLen == 1 {
				for _, char1 := range item {
					for _, char2 := range arr[1][0] {
						tmp = append(tmp, string(char1)+string(char2))
					}
				}
			} else {
				for _, char2 := range arr[1][0] {
					tmp = append(tmp, item+string(char2))
				}
			}
		}
		// 替换切片的前两个元素
		arr = append([][]string{tmp}, arr[2:]...)
		// 继续递归处理剩余的元素组合
		if len(arr[0]) > 0 {
			comb(arr)
		}
	}
	// 调用递归函数生成结果
	comb(code)
	return result
}

2 )方案2: 回溯

import "strings"

// 定义 letterCombinations 函数,接收一个字符串参数 digits,返回一个字符串数组
func letterCombinations(digits string) []string {
	// 如果 digits 为空字符串,直接返回空数组
	if len(digits) == 0 {
		return []string{}
	}
	// 定义电话号码对应的字母组合映射
	phoneMap := map[string]string{
		"2": "abc",
		"3": "def",
		"4": "ghi",
		"5": "jkl",
		"6": "mno",
		"7": "pqrs",
		"8": "tuv",
		"9": "wxyz",
	}
    // 初始化结果数组
	var combinations []string
	// 定义回溯函数
	var backtrack func(index int, combination string)
	backtrack = func(index int, combination string) {
		// 如果索引等于 digits 的长度,将当前组合加入结果数组
		if index == len(digits) {
			combinations = append(combinations, combination)
			return
		}
		// 获取当前数字对应的字母组合
		digit := string(digits[index])
		letters := phoneMap[digit]
		// 遍历当前数字对应的字母组合
		for _, letter := range letters {
			// 将当前字母加入组合
			comb := combination + string(letter)
			// 递归调用回溯函数,增加索引
			backtrack(index+1, comb)
		}
	}
	// 调用回溯函数,从索引 0 开始
	backtrack(0, "")
	// 返回最终的结果数组
	return combinations
}

3 )方案3: 广度优先

func letterCombinations(digits string) []string {
	// 如果 digits 为空字符串,直接返回空数组
	if digits == "" {
		return []string{}
	}
	// 定义电话号码对应的字母组合数组
	phone := []string{"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}
	// 初始化队列,将空字符串作为初始元素
	queue := []string{""}
	// 遍历输入的数字字符串
	for _, digit := range digits {
		// 获取当前队列的长度
		queueLength := len(queue)
		// 创建临时队列用于存储新的组合
		tmpQueue := make([]string, 0)
		// 遍历当前队列中的元素
		for i := 0; i < queueLength; i++ {
			// 从队列中取出一个元素
			tmp := queue[i]
			// 遍历当前数字对应的字母组合
			for _, letter := range phone[digit-'2'] {
				// 将当前元素和字母组合的每个字母拼接,然后加入临时队列
				tmpQueue = append(tmpQueue, tmp+string(letter))
			}
		}
		// 更新队列为新的组合
		queue = tmpQueue
	}
	// 返回最终的结果数组
	return queue
}
UE5实现距离测量功能 阅读详情

相关推荐

【车辆仿真】从0开始建立dSPACE RT Simulink工程:CAN通信(RTICANMM方法)

【工程环境信息】:本文基于链接文章搭建SCALEXIO Rack RTPC总线节点,用于与AutoBox通信硬件:上位机:惠普台式PC(Windows 11专业版)下位机(实时机):AutoBox (DS1006)板卡:DS6342软件:本文所使用的DBC链接提示:以下是本篇文章正文内容,下面案例可供参考!!!的部分一定记得配置,其他的按需配置RTICANMM的灵活度非常高,尽可能参考Help文档,理解相应的配置内容官方有RTICANMM的样例工程,在下方路径。

winnizap的博客 2383

P8467 [Aya Round 1 B] 甲(one)

P8467 [Aya Round 1 B] 甲(one)

m0_65170489的博客 489

滚动时域优化方法

滚动时域优化(Receding Horizon Optimization, RHO),也被广泛称为模型预测控制(Model Predictive Control, MPC),是一种用于动态系统优化和控制的。其核心思想是“在每个当前时刻k,控制器只考虑未来一个(称为“预测时域”或“优化时域”,长度N)内的系统行为。(通过测量或估计得到)。(描述状态如何随输入和干扰变化)。(如果有,可能基于历史数据或假设)。在这个有限的未来时域[k, k+N-1]上,求解一个。这个优化问题的目标是找到一个。

m0_69522810的博客 2301

数据结构与算法笔记:字典序最大问题分析

字典序最大问题 问题描述 给定一个1到n的排列(无序状态的),依次插入到栈中,在每时每刻都可以多次从栈中弹出栈顶 问:应如何使得弹出栈顶的序列的字典序最大,并输出这个序列 问题分析 什么是字典序 比如两个序列:5,4,3,2,1和1,2,3,4,5 这两个中第一个的字典序最大 每个位置上的数字比其他序列上同一位置的数字要大 比如:第一位置中5比1大,第二位置中4比2大这样 即:字典序最大 = 从左向右看这个序列,每个数字都尽量大 题目给定一个1到n的排列,每个数字只出现一次 要使出栈的字典序最大

Wang的专栏 4393

Linux中断子系统分析之(四):驱动程序申请中断

中断子系统中有一个重要的设计机制,那就是Top-half和Bottom-half,将紧急的工作放置在Top-half中来处理,而将耗时的工作放置在Bottom-half中来处理。 如果中断不分上下半部处理,那么意味着只有等上一个中断完成处理后才会打开中断,下一个中断才能得到响应。当某个中断处理处理时间较长时,很有可能就会造成其他中断丢失而无法响应,影响系统性能。 中断分成上下半部处理可以提高中断的响应能力,在上半部处理完成后便将中断打开,这样就可以响应其他中断了,等到中断退出的时候再进行下半部的处理。为了进

m0_46525308的博客 1229

思澈sdk-新建lcd

co5300至此有3个同ID的驱动,在co5300xxxx.c的LCD_DRIVER_EXPORT(co5300, LCD_ID, &lcdc_int_cfg, &CO5300_drv, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT, 2);2 在customer\peripherals\Kconfig_lcd中添加如下配置(注意修改的地方有两个LCD_USING_TFT_CO5300_143)5 在该文件中的config LCD_DPI配置项下添加:(这里300为DPI)

gongyuan073的专栏 1392

数据结构与算法笔记:农夫过河问题python3实现

问题描述 农夫(Human)过河。一个农夫带着一只狼(Wolf),一只羊(Sheep)和一些菜(Vegetable)过河。河边只有一条船,由于船太小,只能装下农夫和他的一样东西。在无人看管的情况下,狼要吃羊,羊要吃菜,请问农夫如何才能使三样东西平安过河? 要求: 输出一行,为最终的过河方式,方案格式为 过河人员、回来人员、过河人员、回来人员、…、过河人员。 过去和回来的人员之间,用空格隔开。 以四...

Wang的专栏 3374

无人机芯片模块技术要点分析

恶劣环境下信号稳定性:无人机在恶劣环境下工作时,遥感系统采集的信号往往很不稳定,视频信号处理芯片需要具备强抗干扰能力,能辨别脉冲脉宽为50ns以上、幅度为0V~4.5V的输入信号。这种架构能兼顾强大的运算能力和灵活的接口控制。芯片小型化:麻省理工学院的研究人员已设计出仅20平方毫米的微型芯片,可处理无人机飞行所需的惯性数据和相机图像,为微型无人机的发展奠定了基础。光子集成芯片(PIC) :研究显示,与电子芯片相比,光子计算芯片在延迟、计算容量和能效上都有数量级的提升,有望解决当前无人机系统的计算瓶颈。

YUNZHUO666的博客 1406

数据结构与算法笔记:计算思维之经典农夫过河问题C++实现

农夫、羊、狼、菜的过河问题 问题描述 角色:农夫,羊,狼,菜 条件1:船很小,只能装下农夫和其他一个角色 条件2:无人看管,羊吃菜,狼吃羊 问:如何让其他三种角色被农夫平安带着过河? 相关分析 我们可以先用人脑尝试一下相关渡河策略 1 ) 先渡狼,人回来再渡菜,人回来再渡羊 2 ) 先渡菜,人回来再渡狼,人回来再渡羊 以上两种很好想到,而且我们可以知道羊这种角色是不能先渡河过去的,羊需要最后再渡 如果先渡了羊了,之后再渡任何其他角色,都要将羊带回来 可以参考小游戏:http://gameschool

Wang的专栏 3312

AIStarter避坑指南:Wan2.2 Animate整合包从下载到出片的完整流程(附常见错误修复)

本文提供了Wan2.2 Animate整合包从下载部署到生成高清视频的完整避坑指南。详细解析了通过AIStarter启动、环境配置、核心参数调优以及七大常见错误(如CUDA内存不足、节点缺失、视频模糊等)的根因与修复方案,帮助用户高效利用ComfyUI工作流,稳定生成720P高质量AI动画视频。

weixin_29052717的博客 706

yolov8 转华为昇腾om脚本

yolov8 转华为昇腾om脚本

jacke121的专栏 1602

数据结构与算法笔记:图搜索之DFS详解

图搜索 Graph Search 图搜索的分类 BFS广度优先(宽搜) DFS深度优先(深搜) !!!本文详解!!! 深度优先搜索DFS 深度优先遍历DFS, 这个策略其实是非常stupid or simple的,比BSF要简单的多 同样,我们可以通过一个故事来开始 在古希腊神话中, Ariadne是Crete的国王Minos的公主,她给忒修斯(Theseus)一个线团 使得忒修斯成功进入迷宫杀死牛头怪兽,但事后忒修斯抛弃了她 这是一个有道德意义的故事又或者存在不同的版本, 但不是我们的研究的对象

Wang的专栏 3118

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

数据结构与算法笔记:计算思维之人鬼渡河问题

人鬼渡河问题 1 ) 问题描述 目标:将东岸的3人3鬼通过一只小船安全转移到西岸,希望摆渡次数尽可能少 条件 船的容量有限,一次最多只能坐2人(或2鬼或1人1鬼) 无论是在河的东岸还是在河的西岸,一旦鬼数多于人数,则人将被鬼吃掉 怎样渡河的大权掌握在人的手中 说明:划船的时间忽略不计。船一靠岸即将船与岸视为一体,人和鬼即使还没有下 船也视为已上岸 任务:编写程序,求出一种渡河方案 备注:图片托管于github,请确保网络的可访问性 2 ) 分析 目标是找

Wang的专栏 2447

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

数据结构与算法之二叉树: LeetCode 701. 二叉搜索树中的插入操作 (Ts版)

1 ) 方案1:模拟。2 ) 方案2:递归。

Wang的专栏 2270

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

数据结构与算法笔记:计算思维之下楼梯台阶和象棋跳马问题

下台阶问题 1 ) 问题描述 从楼上走到楼下共有 h 个台阶,每一步有三种走法 走一个台阶; 走二个台阶; 走三个台阶。 问:一共可以走出多少种方案? 即共要多少步? 每一步走几级台阶? 2 ) 分析 初始思路 我们根据题目给定的场景,先简单模拟一下,设定 h=4h=4h=4 备注:图片托管于github,请确保网络的可访问性 如上图所示, 这里有4阶楼梯, 红色数字代表每一步走几级台阶 这里枚举了4层台阶的所有可能情况, 但是不管具体有几级台阶,下

Wang的专栏 2111

Python笔记:滑动验证码的识别算法

概述 用程序识别极验滑动验证码的验证,包括分析识别思路、识别缺口位置、生成滑块拖动路径、模拟实现滑块拼合通过验证等步骤。 准备工作 使用Python库是Selenium,浏览器为Chrome。请确保已安装Selenium库和ChromeDriver浏览器驱动。 关于极验滑动验证码: 极验滑动验证码官网为:http://www.geetest.com/ 验证方式为拖动滑块拼合图像,若图像完全拼合...

Wang的专栏 2103

数据结构与算法之堆: LeetCode 295. 数据流的中位数 (Ts版)

/ 返回 1.5 ((1 + 2) / 2)中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。3 ) 方案3:有序集合 + 双指针。2 ) 方案2:优先队列-优化版。1 ) 方案1:优先队列。

Wang的专栏 1907

数据结构与算法笔记:计算思维之谁做的好事与刑侦作案问题

谁做的好事 清华附中有四位同学中的一位做了好事,不留名,表扬信来了之后,校长问这四位是谁做的好事。 A说:不是我。 B说:是C。 C说:是D。 D说:他胡说。 已知:三个人说的是真话,一个人说的是假话。 现在请你根据这些信息,编写程序找出做了好事的人。 分析 将四个人说的四句话(自然语言)转换成计算机可以计算的式子, 可使用循环枚举的方式来判断 (1) 思路一:通过字符表示人 先定义一个字符变量 thisman 表示要寻找的做了好事的人的“名字(代号)”(A、B、C、D),即 char this

Wang的专栏 1829

数据结构与算法笔记:图搜索之BFS详解

图搜索 Graph Search 图搜索的分类 BFS广度优先(宽搜) DFS深度优先(深搜) 广度优先搜索BFS 我们可以用比喻来说明广度优先搜索算法 在一片草木枯黄的深秋草原上,在草原的某一处出现了一处野火 一开始的时候野火集中于一点之上,在这点野火耗尽当前植被变成灰烬之前点燃了周围的植被 比如节点s是初始火种,假设我们手中有一个秒表,每过1秒,我们的大火会向外迈进一步 这个过程只能向外,不能向内,因为只能点燃植被,不能把灰烬点燃 蓝色的点是即将变为灰烬的点,红色的点是刚被点燃的点,灰色的圆形或

Wang的专栏 1791

数据结构与算法之动态规划: LeetCode 1494. 并行课程 II (Ts版)

给你一个整数 n 表示某所大学里课程的数目,编号为 1 到 n ,数组 relations 中, relations[i] = [xi, yi] 表示一个先修课的关系,也就是课程 xi 必须在课程 yi 之前上。解释:上图展示了题目输入的图。一个最优方案是:第一学期上课程 2 和 3,第二学期上课程 4 ,第三学期上课程 1 ,第四学期上课程 5。然后第二个学期上课程 1 ,第三个学期上课程 4。在一个学期中,你 最多 可以同时上 k 门课,前提是这些课的先修课在之前的学期里已经上过了。

Wang的专栏 1749

数据结构与算法笔记:求直方图最大面积算法分析

直方图最大面积 问题描述 有n列的直方图,第j列高度为hjh_jhj​, 求一个面积最大的子矩阵 备注:图片托管于github,请确保网络的可访问性 格式要求 输入第一行正整数n,第二行n个空格隔开的非负整数 数据范围: 所有直方图的列不会超过30000 关键算法实现 1 ) 算法1:时间复杂度为: O(n3)O(n^3)O(n3)的实现 分析 矩形面积为底和高的乘积 底部从a到b,那么底边长为: b-a+1 高为:min{hi∣a≤i≤b}min \{h

Wang的专栏 1664

数据结构与算法之LRU: 实现 LRU 缓存算法功能 (Ts, Py, Go版)

LRU - Lease Recently Used 最近使用如果内存优先,只缓存最近使用的,删除 ‘沉睡’ 数据核心 api: get set分析。

Wang的专栏 1599

数据结构与算法之贪心: LeetCode 455. 分饼干 (Ts, Py, Go版)

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j]。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。2 )排序 + 双指针 + 贪心。1 )排序 + 遍历。

Wang的专栏 1566

动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100

将一个复杂问题拆分成多个规模更小的子问题,通过保存子问题的计算结果,避免重复计算,最终得到原问题的答案。先看一个经典问题。dp[i] = 以第 i 个元素结尾的最优结果例如最长递增子序列。最长递增子序列不一定以最后一个元素结尾,因此必须遍历整个数组取最大值。dp[i] = 前 i 个元素的最优结果这种情况下,最终答案通常就是dp[n]。关键在于理解 dp 数组的定义。动态规划的核心并不是背诵某个固定模板,而是建立正确的状态定义,并通过状态转移方程解决问题。dp[i] 或 dp[i][j] 表示什么?

zengjiajun2006的博客 794

LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)

LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等) 题目描述: 给定三个字符串 s1、s2、s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串: - s = s1 + s2 + ... + sn - t = t1 + t2 + ... + tm - |n - m| <= 1 - 交错 是 s1 + t

huayimenghan的博客 212

LeetCode 每日一题 2026/11/2-2026/11/8

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步

AlphaTao的博客 186
上一篇: 数据结构与算法之字符串: LeetCode 20. 有效的括号 (Ts, Py, Go, Java版)
下一篇: 数据结构与算法之数组: LeetCode 914. 卡牌分组 (Ts, Py, Go版)
Wang's Blog
博客等级 码龄12年 7433粉丝 2421原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值