zoukankan      html  css  js  c++  java
  • 有n个数(两两不同),对于这n个数的每个连续子序列,把其中最大的一个数标记一次,问最后每个数被标记次数

    今天在qq群了看到了这个题目,觉得用单调栈的解法挺好,可以在o(n)内搞定,特意记录下来

    首先明确单调栈的含义:

    栈是FILO的,栈的所有操作都是在栈顶进行。

    单调性指的是当前栈中存储的元素是严格的递增或者递减。

    递增:栈中元素从栈顶到栈底是严格递增的; 递减:栈中元素从栈顶到栈底是严格递减的。

    举例:先后入栈的元素假设为9,3,10,1,15。。

    考虑递增栈:

    初始时,栈为空;

    9入栈,栈当前为(9)

    3入栈,栈不变

    10入栈,9出栈,栈当前为(10)

    1入栈,栈不变

    15入栈,10出栈,栈当前为(15)

    本题目解读:(群中出题者给的例子)

    举例:

    输入={1, 4, 2, 3}

    初始标记都是0={0, 0, 0, 0}

    取子区间[1, 4] 最大数是4 所以4做一次标记 标记变为{0, 1, 0, 0}

    子区间[1, 3] 最大数还是4 {0, 2, 0 ,0}

    [1, 2] {0, 3, 0, 0}

    ……

    这样遍历所有的n*(n-1)/2子区间之后 输出当前标记数组即可
     
    解题思路:依次遍历每个数,利用单调栈的思路,找到每个数前面第一个比它大的数,再找到后面第一个比它大的数。然后直接计算当前数对应的结果。。
    比如说:{5,1, 4, 2, 3,6}
    假设当前遍历到了数4,则前面第一个比它的是5,后面第一比它大的是6,显然,当某个子序列最大值为4时,这个子序列不能包含5和5前面的数,也不能包含6和6后面的数,所以直接考虑区间{1,4,2,3}中4能作为最大数的子序列个数count,count即为4对应的最后结果。
    计算公式:假设4前面数的个数为m(这些数均小于4),4后面的个数为n(这n个数均小于4),m和n可以由下标计算得到,于是有:
    (1)4不作为序列边界的序列数count1 = m * n;
    (2)4作为序列边界的序列数count2 = m + n;
    所以可知: count = count1+count2 = m*n+m+n;
     
    依次计算每个数的count值,即可在o(n)内解决这道题。
     
  • 相关阅读:
    mybatis框架查询用户表中的记录数
    文件的上传和下载
    怎样在一条sql语句中将第一列和第二列加和的值作为第三列的值
    [OS] 进程的虚地址空间
    [网络] TCP/IP协议族各层的协议汇总
    [面试] C++ 虚函数表解析
    [OS] 堆栈、堆、数据段、代码段
    [算法] 并查集概念及其实现
    [OS] 我与大牛的对话!
    [C] int *p[4]与int (*q)[4]的区别
  • 原文地址:https://www.cnblogs.com/xlzhh/p/4415731.html
Copyright © 2011-2022 走看看