Python 算法题学习笔记一

文章目录

题目

在终端穿戴场景中,往往涉及到用户和终端设备之间的语音交互,通常由用户唤醒相关的设备并进行语音命令控制设备完成相应的操作,设备在收到语音命令时会对用户的意图进行识别,例如识别"拍照""摄像"等意图,从而进行对应的操作。要求使用 KNN 算法对用户输出的语音特征进行分类:语音片段经过特征提取后是一个 3 3 3 维的向量所有距离使用欧式距离公式计算,即对于两个 N N N 维向量 x ⃗ = ( x 1 , x 2 , ... , x N ) , y ⃗ = ( y 1 , y 2 , ... , y N ) \vec{x} = (x_1, x_2, \dots, x_N), \quad \vec{y} = (y_1, y_2, \dots, y_N) x =(x1,x2,...,xN),y =(y1,y2,...,yN)两个向量间的距离为: d ( x ⃗ , y ⃗ ) = ∑ k = 1 N ( x k − y k ) 2 d_{(\vec{x}, \vec{y})} = \sqrt{\sum_{k=1}^{N} (x_k - y_k)^2} d(x ,y )=∑k=1N(xk−yk)2 。

  • 输入描述第一行:正整数 N N N 和 K K K,分别表示给定的已知语音特征向量的数量和邻居数量
  • K K K第 2 ~ 13 行:已知语音的特征向量和 l a b e l label label,其中最后一位表示类别 l a b e l label label
  • 第 14 行:待分类的语音特征向量

输入

python 复制代码
10 3
0.5 0.3 0.4 0
0.6 0.2 0.5 0
0.4 0.3 0.3 0
0.7 0.4 0.6 0
2.1 2.3 2.2 1
2.3 2.2 2.4 1
2.2 2.4 2.3 1
4.5 4.3 4.4 2
4.4 4.5 4.6 2
4.6 4.4 4.5 2
2.2 2.1 2.3

输出

python 复制代码
1

答案

python 复制代码
#1.读入数据
n , k = map(int , input().split())
datas = [list(map(float , input().split())) for _ in range(n)]
test = list(map(float , input().split()))
#2.封装距离函数
def dist (x , y):
    n = len(x)
    ans = 0
    # 对每个维度求平方差的和
    for i in range(n):
        ans += (x[i] - y[i]) ** 2
    # 注意,为了获得更高的精度和效率,我们可以直接返回平方差的和,而不进行开方操作。
    return ans

# 3.排序并选取前k个最近邻
datas.sort(key = lambda x : dist(x[:-1] , test))
# 4.统计前k个最近邻的标签出现频率,并选取出现频率最高的标签作为预测结果
# 注意:这里有可能k大于n,所以我们需要取min(n , k)来保证不会越界
real_k = min(n , k)
target_datas = datas[:real_k]
# 5.哈希统计: 统计每个标签出现的频率 (类别,频率)
mp = {}
for data in target_datas:
    label = data[-1]
    if label not in mp:
        mp[label] = 1
    else:
        mp[label] += 1
# 6.选取出现频率最高的标签作为预测结果
res = list(mp.items())
res.sort(key = lambda x : -x[1])
print(int(res[0][0]))

datas = [list(map(float , input().split())) for _ in range(n)]

  • input():
    从控制台读取一行输入。
    结果:得到一个字符串 "1.5 2.5 3.5"
  • .split():
    将这个字符串按空格分割成多个子串。
    结果:得到一个字符串列表 ['1.5', '2.5', '3.5']
  • map(float, ...):
    map 函数会将前面得到的列表中的每一个字符串,都执行一次 float()(转换为浮点数)操作。
    结果:得到一个包含 1.5、2.5、3.5 的 map 迭代器对象。
  • list(...):
    因为 map 返回的是一个迭代器,我们需要用 list() 把它真正转换成 Python 的列表。
    结果:得到一个纯数字列表 [1.5, 2.5, 3.5]

datas.sort(key = lambda x : dist(x[:-1] , test))

匿名函数的用法

python 复制代码
lambda 参数列表 : 表达式

假设我们要写一个求两个数字平方和的函数:

使用传统的 def 定义:

python 复制代码
def square_sum(x, y):
    result = x**2 + y**2
    return result

print(square_sum(3, 4))  # 输出 25

使用 lambda 一行搞定:

python 复制代码
square_sum_lambda = lambda x, y : x**2 + y**2

print(square_sum_lambda(3, 4))  # 输出 25

List 的切片操作

提取从开头到倒数第一个元素之前的所有元素

python 复制代码
x[:-1]

Python 的切片(Slicing)操作不仅优雅,而且极其强大。它的完整语法其实包含三个参数:

sequence[start : stop : step]

  • start:起始索引(包含该位置)。默认是 0。

  • stop:结束索引(不包含该位置)。默认是序列的结尾。

  • step:步长(每次跳过几个元素)。默认是 1。

如果数据是 data = [10, 20, 30, 40, 50, 60, 70, 80, 90]

负数索引(从后往前数)

  • 去掉首尾的边界数据(比如去除可能存在的噪声边缘):
python 复制代码
print(data[1:-1])
# 输出: [20, 30, 40, 50, 60, 70, 80] (去掉了首部的 10 和尾部的 90)
  • 获取最后 3 个数据点:
python 复制代码
print(data[-3:])
# 输出: [70, 80, 90]

列表的 .sort() 方法

  1. 使用内置函数作为 key
python 复制代码
words = ["apple", "banana", "kiwi", "pear"]

# 默认排序(按首字母)
words.sort()
print(words)  # 输出: ['apple', 'banana', 'kiwi', 'pear']

# 使用 key=len(按长度排序)
words.sort(key=len)
print(words)  # 输出: ['kiwi', 'pear', 'apple', 'banana']
  1. 结合 lambda 处理复合数据
python 复制代码
students = [("Alice", 88), ("Bob", 95), ("Charlie", 72)]

# x 代表列表中的每一个元组,x[1] 提取出了成绩作为排序依据
students.sort(key=lambda x: x[1])

print(students)
# 输出: [('Charlie', 72), ('Alice', 88), ('Bob', 95)]
  1. 多重条件排序
python 复制代码
students = [("Alice", 88), ("Bob", 95), ("Charlie", 88)]

# 成绩取负数 (-x[1]) 实现数值的降序,名字 x[0] 默认升序
students.sort(key=lambda x: (-x[1], x[0]))

print(students)
# 输出: [('Bob', 95), ('Alice', 88), ('Charlie', 88)]

注意比较多个条件的时候,需要将多个值打包为一个单独的数据结构,常见的是 元组 Tuple。

简单来说,我们不能写成 key = lambda x: a, b(这样 Python 会因为参数解析混乱而报语法错误),你必须加上括号,写成 key = lambda x: (a, b)。

if label not in mp:

多条件分支

python 复制代码
if score >= 90:
    print("优秀")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")

结合逻辑运算符 (and, or, not, in, not in)

python 复制代码
is_vip = False
if not is_vip:
    print("您还不是会员,请先充值")

隐式布尔值判断

Python 规定,以下这些值在 if 判断中会自动被当成 False(称为假值):

  • 数字零:0, 0.0

  • 空序列:空字符串 ""、空列表 []、空元组 ()

  • 空字典:{}

  • 空值:None

除了上述假值,其他所有的值都会被当成 True。

推导式中的过滤守卫 (Filter in Comprehensions)

基于某个条件从一个列表中筛选出符合要求的数据

python 复制代码
data = [12, -5, 30, -8, 55, 0]

# 需求:提取出所有大于 0 的数字,并把它们乘以 2
# 语法:[计算逻辑 for 变量 in 集合 if 过滤条件]
positive_doubled = [x * 2 for x in data if x > 0]

print(positive_doubled)  
# 输出: [24, 60, 110]

res = list(mp.items())

  • mp.items():这是字典(Dictionary)自带的一个非常重要的方法。它会把字典里所有的键值对,打包成一个个元组(Tuple)。

    • 假设前面统计的 mp 是 {'类别0': 2, '类别1': 5}。

    • mp.items() 就会把它变成类似 [('类别0', 2), ('类别1', 5)] 的结构。

  • list(...):强制类型转换。因为 mp.items() 返回的是一个动态的"视图(View)"对象,不能直接用来排序和切片。所以用 list() 把它固化成一个真正的 Python 列表,赋值给变量 res。

在 PyCharm 中(或者说在任何标准的 Python 3 环境下)运行 mp.items(),它返回的并不是一个列表(List),而是一个特殊的内置对象类型:dict_items(字典视图对象)。

python 复制代码
mp = {'正常流量': 100, 'DDoS攻击': 5}
items_obj = mp.items()

print(type(items_obj))  # 输出: <class 'dict_items'>
print(items_obj)        # 输出: dict_items([('正常流量', 100), ('DDoS攻击', 5)])

当我们执行 res = list(mp.items()) 时,Python 生成的是这个结构:

python 复制代码
res = [('正常流量', 100), ('DDoS攻击', 5)]
  • 外层是一个中括号 [],代表这是一个列表。

  • 内层是一个个小括号 (),代表里面装的元素是元组(Tuple)。

相关推荐
qqty12172 小时前
Java进阶学习之路
java·开发语言·学习
沉鱼.442 小时前
第六届题目
算法
_李小白2 小时前
【OSG学习笔记】Day 22: StateSet 与 StateAttribute (渲染状态)
笔记·学习
黑眼圈子2 小时前
总结一下用Java做算法的常用类和方法
java·开发语言·算法
apcipot_rain2 小时前
天梯赛练习集 时间规划 限时复盘 中档题详解(L1-6~L2-4)
算法
码界筑梦坊2 小时前
353-基于Python的大湾区气候数据可视化分析系统
开发语言·python·信息可视化·数据分析·django·vue·毕业设计
再卷也是菜3 小时前
第一章、线性代数(2)高斯消元法
线性代数·算法
NAGNIP3 小时前
一文搞懂CNN经典架构-EfficientNet!
算法·面试
如何原谅奋力过但无声3 小时前
【chap11-动态规划(上 - 基础题目&背包问题)】用Python3刷《代码随想录》
数据结构·python·算法·动态规划