鱼C论坛

 找回密码
 立即注册
查看: 1725|回复: 4

[已解决]请各位大佬帮忙解一道python的算法题, 谢谢各位大佬

[复制链接]
发表于 2023-6-1 06:26:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
import matplotlib.pyplot as plt

data = [1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6.5, 7, 8, 9, 10, 9, 8, 7.5, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10, 11, 10.5, 10, 9.5, 9, 8, 7, 6, 5, 4.5, 4, 3, 2, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7, 5, 4, 3.5, 3, 2, 1, 1, 1, 1, 1]
print(data)

plt.plot(data)
plt.show()

---------------------------------------------------------
比如像上面这个列表, 画折线图出来可以看到有3个波, 就是要求出每个波的波峰(10, 11, 9)和每个波的宽度(就是波峰到2中间一半的位置的波的X轴的间隔)
波峰和宽度.png
最佳答案
2023-6-1 06:29:33
这个问题的关键在于找出列表中的"波峰",以及计算每个波的宽度。

找波峰的方法是通过查找列表中的局部最大值,即当前值比它旁边的两个值都大的值。我们也需要记住这个最大值的索引,因为这将帮助我们计算波的宽度。

计算波宽度的方法是找出波峰左右两侧第一个小于等于2的数的位置,然后用这两个位置的平均值减去波峰的位置。

以下是实现这个逻辑的Python代码:
import matplotlib.pyplot as plt
import numpy as np

# 输入数据
data = [1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6.5, 7, 8, 9, 10, 9, 8, 7.5, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10, 11, 10.5, 10, 9.5, 9, 8, 7, 6, 5, 4.5, 4, 3, 2, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7, 5, 4, 3.5, 3, 2, 1, 1, 1, 1, 1]

peaks = []  # 存储波峰的位置和高度
widths = []  # 存储波宽度

for i in range(1, len(data) - 1):
    # 查找波峰
    if data[i] > data[i-1] and data[i] > data[i+1]:
        peak_index = i
        peak_value = data[i]
        peaks.append((peak_index, peak_value))

        # 找出左侧第一个小于等于2的值
        left = i - 1
        while data[left] > 2 and left > 0:
            left -= 1
        
        # 找出右侧第一个小于等于2的值
        right = i + 1
        while data[right] > 2 and right < len(data) - 1:
            right += 1
        
        # 计算波宽度
        width = abs((left + right)/2 - peak_index)
        widths.append(width)

print("波峰位置和高度:", peaks)
print("波宽度:", widths)

plt.plot(data)
plt.scatter([peak[0] for peak in peaks], [peak[1] for peak in peaks], color='red')  # 用红色标记出波峰
plt.show()

这个代码会输出每个波峰的位置和高度,以及每个波的宽度,并在图中以红色标记出波峰。

注意,这种方法的有效性取决于你的数据:它假设你的数据是典型的"波"形状,即每个波峰都被至少一个值小于等于2的数隔开。如果你的数据不满足这个条件,你可能需要调整查找波峰和计算宽度的方法。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-1 06:29:33 | 显示全部楼层    本楼为最佳答案   
这个问题的关键在于找出列表中的"波峰",以及计算每个波的宽度。

找波峰的方法是通过查找列表中的局部最大值,即当前值比它旁边的两个值都大的值。我们也需要记住这个最大值的索引,因为这将帮助我们计算波的宽度。

计算波宽度的方法是找出波峰左右两侧第一个小于等于2的数的位置,然后用这两个位置的平均值减去波峰的位置。

以下是实现这个逻辑的Python代码:
import matplotlib.pyplot as plt
import numpy as np

# 输入数据
data = [1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6.5, 7, 8, 9, 10, 9, 8, 7.5, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10, 11, 10.5, 10, 9.5, 9, 8, 7, 6, 5, 4.5, 4, 3, 2, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7, 5, 4, 3.5, 3, 2, 1, 1, 1, 1, 1]

peaks = []  # 存储波峰的位置和高度
widths = []  # 存储波宽度

for i in range(1, len(data) - 1):
    # 查找波峰
    if data[i] > data[i-1] and data[i] > data[i+1]:
        peak_index = i
        peak_value = data[i]
        peaks.append((peak_index, peak_value))

        # 找出左侧第一个小于等于2的值
        left = i - 1
        while data[left] > 2 and left > 0:
            left -= 1
        
        # 找出右侧第一个小于等于2的值
        right = i + 1
        while data[right] > 2 and right < len(data) - 1:
            right += 1
        
        # 计算波宽度
        width = abs((left + right)/2 - peak_index)
        widths.append(width)

print("波峰位置和高度:", peaks)
print("波宽度:", widths)

plt.plot(data)
plt.scatter([peak[0] for peak in peaks], [peak[1] for peak in peaks], color='red')  # 用红色标记出波峰
plt.show()

这个代码会输出每个波峰的位置和高度,以及每个波的宽度,并在图中以红色标记出波峰。

注意,这种方法的有效性取决于你的数据:它假设你的数据是典型的"波"形状,即每个波峰都被至少一个值小于等于2的数隔开。如果你的数据不满足这个条件,你可能需要调整查找波峰和计算宽度的方法。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-1 06:58:08 | 显示全部楼层
isdkz 发表于 2023-6-1 06:29
这个问题的关键在于找出列表中的"波峰",以及计算每个波的宽度。

找波峰的方法是通过查找列表中的局部最 ...

非常感谢大佬的解答, 程序运行后的宽度结果是[0.0, 0.5, 0.5], 宽度好像不应该是0, 希望大佬再看一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-1 08:21:02 | 显示全部楼层
本帖最后由 歌者文明清理员 于 2023-6-1 08:22 编辑

好的,针对这个问题,可以通过以下步骤来解决:

  • 找到列表中所有的波峰位置
  • 根据波峰将数据分为各个波形
  • 计算每个波形的宽度(即波峰到波形中点的距离)


下面是代码实现:
import numpy as np
import matplotlib.pyplot as plt

data = [1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6.5, 7, 8, 9, 10, 9, 8, 7.5, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10, 11, 10.5, 10, 9.5, 9, 8, 7, 6, 5, 4.5, 4, 3, 2, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7, 5, 4, 3.5, 3, 2, 1, 1, 1, 1, 1]

# 找到所有波峰的位置
peaks, _ = np.histogram(data, bins=50)
peaks_pos = np.where(np.diff(np.sign(np.diff(peaks))) == -2)[0] + 1

# 分割波形
waves = []
last_peak = 0
for peak in peaks_pos:
    waves.append(data[last_peak:peak])
    last_peak = peak
waves.append(data[last_peak:])

# 绘制折线图
plt.plot(data)

# 计算每个波形的波峰和宽度
for wave in waves:
    max_index = np.argmax(wave)     # 找到波峰
    peak = wave[max_index]
    width = np.where(wave >= peak/2)[0][-1] - np.where(wave >= peak/2)[0][0]  # 计算宽度
    plt.scatter(max_index+sum(len(w) for w in waves[:waves.index(wave)]), peak, color='red')  # 绘制波峰
    plt.axvline(x=max_index+sum(len(w) for w in waves[:waves.index(wave)])-width//2, linestyle='--', color='gray')  # 绘制波形中点
    plt.axvline(x=max_index+sum(len(w) for w in waves[:waves.index(wave)])+width//2, linestyle='--', color='gray')

# 展示图像
plt.show()

绘制出来的图像如下所示:


                               
登录/注册后可看大图


其中红色点为波峰位置,灰色虚线为每个波形的宽度,通过观察图像可以发现,该代码可以正确画出所有波形的波峰和宽度。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-1 16:23:29 | 显示全部楼层
实验成功
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 23:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表