解决leetcode第4017题数组中的峰值II

4017.数组中的峰值II

难度:困难

问题描述:

给你一个长度为n的整数数组nums和一个二维整数数组queries。

如果满足以下条件,子数组numsi..j被称为峰值子数组:

其长度至少为3。

存在一个下标k使得i<k<j且:

numsk>numsk-1

numsk>numsk+1

你需要处理以下两种类型的查询:

1,li,ri:计算完全包含在numsli..ri中的峰值子数组的数量。

2,indexi,vali:将numsindexi更新为vali。此更新适用于所有后续查询。

返回一个数组answer,其中answeri是按出现顺序排列的第i个类型1查询的答案。

子数组是数组中连续的非空元素序列。

示例1:

输入:nums=1,3,2,4,queries=\[1,0,3,2,1,1,1,0,3]

输出:2,0

解释:

查询1,0,3

1,3,2:选择k=1。则numsk=3,numsk-1=1,且numsk+1=2。因为3>1且3>2,这是一个峰值子数组。

1,3,2,4:选择k=1。则numsk=3,numsk-1=1,且numsk+1=2。因为3>1且3>2,这是一个峰值子数组。

查询2,1,1:将nums1更新为1。数组变为1,1,2,4

查询1,0,3:现在没有峰值子数组。

因此,answer=2,0

示例2:

输入:nums=9,8,9,8,queries=\[1,1,3,2,2,1,1,0,2]

输出:1,0

解释:

查询1,1,3

nums1..3=8,9,8:选择k=2。则numsk=9,numsk-1=8,且numsk+1=8。因为9>8且9>8,这是一个峰值子数组。

查询2,2,1:将nums2更新为1。数组变为9,8,1,8

查询1,0,2:没有峰值子数组。

因此,answer=1,0

示例3:

输入:nums=3,6,2,7,1,queries=\[1,1,3,2,3,0,1,0,4]

输出:0,3

解释:

查询1,1,3:唯一长度至少为3的子数组是6,2,7。其唯一可能的峰值下标是k=2,但nums2=2小于nums1=6和nums3=7,因此它不是一个峰值子数组。

查询2,3,0:将nums3更新为0。数组变为3,6,2,0,1

查询1,0,4

3,6,2:选择k=1。则numsk=6,numsk-1=3,且numsk+1=2。因为6>3且6>2,这是一个峰值子数组。

3,6,2,0:选择k=1。则numsk=6,numsk-1=3,且numsk+1=2。因为6>3且6>2,这是一个峰值子数组。

3,6,2,0,1:选择k=1。则numsk=6,numsk-1=3,且numsk+1=2。因为6>3且6>2,这是一个峰值子数组。

因此,answer=0,3

提示:

3<=n==nums.length<=10**5

0<=numsi<=10**5

1<=queries.length<=10**5

queriesi=1,li,ri或queriesi=2,indexi,vali

0<=li<ri<=n-1

0<=indexi<=n-1

0<=vali<=10**5

分析问题:

解决下面几个小问题,这道题也就迎刃而解了。

一是对于一个数组,先找出其中有多少个峰值,把索引号0和峰值对应的索引号以及最后一个元素的索引号n-1以列表的形式返回,如果中间没有峰值,则返回空列表,函数get_list_of_peak_index(nums1)实现这一功能;

二是对于只有一个峰值的数组nums2,k=start,peak,end,描述了一个查询,如何把这个查询中的不同峰值子数组数量统计出来呢?函数get_numbers_of_peak_sub_array(k,nums2)实现这一功能,最后返回统计出来的峰值子数组数量t和不同的子数组列表temp;

三是处理第一种查询1,li,ri,先根据查询,取出对应的子数组,然后查出子数组中的峰值列表,把这个峰值对应的索引号列表比如0,i1,i2,i3,......,in,n-1,分解成多个小部分,0,i1,i2i1,i2,i3i2,i3,i4、......,每一个部分只有一个峰值,然后调用函数get_numbers_of_peak_sub_array(k,nums2)依次统计每个小部分中峰值子数组的数量,最后将所有峰值子数组数量加起来,就是这个查询对应的峰值子数组的总数量,返回总数量和对应的峰值子数组列表temp;

四是处理第二种查询2,indexi,vali],函数get_changed_nums(query2,nums)实现了这一功能,返回新的nums;

主程序根据查询序列queries,依次取出查询,调用相应的查询处理函数,输出每次查询结果,问题得到解决。

程序如下:

python 复制代码
#统计一个数组nums中峰值子数组的峰值索引号列表t并返回
def get_list_of_peak_index(nums1):
    t=[0]
    n=len(nums1)
    for i in range(n-1):
        if nums1[i] > nums1[i - 1] and nums1[i] > nums1[i + 1]:
            t.append(i)
    t.append(n-1)
    if len(t)<3:
        return []
    else:
        return t

# 统计一个最大的峰值数组nums中峰值子数组的数量并返回
def get_numbers_of_peak_sub_array(k,nums2):
    n=len(nums2)
    start=k[0]
    peak=k[1]
    end=k[2]
    t=(peak-start)*(end-peak-1)
    temp=[]
    for i in range(start,peak):
        for j in range(peak+1,end):
            sub_array=nums2[i:j+1]
            temp.append(sub_array)
    return t,temp

#对查询[2,indexi,vali]的处理,返回处理之后的nums
def get_changed_nums(query2,nums):
    nums[query2[1]]=query2[2]
    return nums

#对查询[1,li,ri]的处理,返回处理之后得到的完全包含其中的峰值子数组数量
def get_numbers_of_peak_subarray_by_query(query1,nums3):
    nums4=nums3[query1[1]:query1[2]+1]
    t = get_list_of_peak_index(nums4)
    if not t:
        return 0,[]
    else:
        n = 0
        r = len(t)
        temp=[]
        for i in range(r - 2):
            a = t[i]
            b = t[i + 1]
            c = t[i + 2] + 1
            k = [a, b, c]
            m, e = get_numbers_of_peak_sub_array(k, nums4)
            temp.extend(e)
            n += m
        return n,temp

#主程序
nums=eval(input('pls input nums='))
queries= eval(input('pls input queries='))
t=[]
for query in queries:
    if query[0]==1:
        n,a=get_numbers_of_peak_subarray_by_query(query,nums)
        s='有以下峰值子数组:' if n!=0 else '没有峰值子数组'
        print(f'对于查询{query},{s}')
        if a:
            print(a)
        t.append(n)
    else:
        k=nums[::]
        nums=get_changed_nums(query,nums)
        print(f'对于查询{query},使得原数组{k}变为{nums}')
print('answer =',t)

运行实例一

pls input nums=1,3,2,4

pls input queries=\[1,0,3,2,1,1,1,0,3]

对于查询1, 0, 3,有以下峰值子数组:

\[1, 3, 2\], \[1, 3, 2, 4\]

对于查询2, 1, 1,使得原数组1, 3, 2, 4变为1, 1, 2, 4

对于查询1, 0, 3,没有峰值子数组

answer = 2, 0

运行实例二

pls input nums=9,7,9,7,9,2

pls input queries=\[1,0,3,2,1,10,1,0,5]

对于查询1, 0, 3,有以下峰值子数组:

\[9, 7, 9, 7\], \[7, 9, 7\]

对于查询2, 1, 10,使得原数组9, 7, 9, 7, 9, 2变为9, 10, 9, 7, 9, 2

对于查询1, 0, 5,有以下峰值子数组:

\[9, 10, 9\], \[9, 10, 9, 7\], \[9, 10, 9, 7, 9\], \[10, 9, 7, 9, 2\], \[9, 7, 9, 2\], \[7, 9, 2\]

answer = 2, 6

运行实例三

pls input nums=3,6,2,7,1

pls input queries=\[1,1,3,2,3,0,1,0,4]

对于查询1, 1, 3,没有峰值子数组

对于查询2, 3, 0,使得原数组3, 6, 2, 7, 1变为3, 6, 2, 0, 1

对于查询1, 0, 4,有以下峰值子数组:

\[3, 6, 2\], \[3, 6, 2, 0\], \[3, 6, 2, 0, 1\]

answer = 0, 3

相关推荐
带多刺的玫瑰1 小时前
Leecode#29刷题之两数相除
java·python·算法
午彦琳1 小时前
2026.9.9
数据结构·算法·leetcode
卷无止境1 小时前
AI Agent编程中,重构节奏与安全检查的门道
后端·python
luj_17681 小时前
中锋卡位与开放线博弈
c语言·开发语言·网络·经验分享·算法
慧都小妮子1 小时前
用 Python 批量把 PDF 参考文献排成 MLA 格式:Spire.Doc for Python 实战
python·pdf·c#·spire.doc·mla格式·参考文献排版·pdf批量处理
洋不写bug1 小时前
二叉树(四)经典算法题目解析,公共祖先,二叉树构造,非递归遍历
数据库·算法·二叉树·二叉树构造·公共祖先
卷无止境1 小时前
AI编程时代,代码复杂性正在悄悄失控
后端·python
开源量化GO1 小时前
看到“2026年 Python 与 API”时,用示例和拆解看清关系
人工智能·python
高洁012 小时前
大模型是怎么“学会“的:预训练、微调、对齐三段论
python·深度学习·transformer·知识图谱·tornado