解决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,i2、i1,i2,i3、i2,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

相关推荐
Bruce_Liuxiaowei28 分钟前
元组与具名元组:把「第 3 个字段」变成「price」
数据结构·python·语法·元组
___波子 Pro Max.31 分钟前
pip 管库,pipx 管工具:Python 依赖隔离的正确姿势
python
Zootopia62633 分钟前
美国载人飞船Crew-13明晚发射!
人工智能·算法·机器学习·数学建模·无人机·创业创新·信息与通信
zhangfeng11331 小时前
qjlDim 含义 TurboQuant QJL Quantized Johnson-Lindenstrauss,量化JL随机投影
人工智能·算法·ai编程·npu
HwJack201 小时前
【HarmonyOS开发小实践】HarmonyOS GC 引用计数 vs 对象追踪,三种回收算法
jvm·算法·harmonyos
blxr_1 小时前
力扣hot100前k个高频元素https://leetcode.cn/problems/top-k-frequent-elements/
算法·leetcode·职场和发展
我的xiaodoujiao2 小时前
Django 基础知识详细图文教程 12-Django 模型定义与使用 2
后端·python·django
happylifetree10 小时前
Python09:核心语法-数据存储与运算-字面量
python
longlongzihan10 小时前
LeetCode 17电话号码的字母组合:回溯算法(DFS)详解
c++·算法·leetcode·深度优先
心之语歌11 小时前
Tkinter 画布基本梳理
运维·服务器·python