pta求阶乘序列前n项和_序列问题总结-超级巧妙

最近发现两个题目,用栈解决非常精巧,特此分享:

leetcode456:

给定一个整数序列:a1, a2, ..., an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj。设计一个算法,当给定有 n 个数字的序列时,验证这个序列中是否含有132模式的子序列。

解法:

如果你从前往后去找的话,你需要

第一: 找到以后后面比前面大的数字

第二:找到一个位于这两个数字之间的数字,且位置在前两个位置之后

但是如果你从后往前找:

先找到ak<aj然后维护这个“最小值”尽可能大就好。一旦找到低于这个最小值的数就可以了。

我们要做大就是如何找到这个最小大最大值,画图可以看出来:

拿到B之后最小数值是A ->更新最小值,拿到c后最小值是B->更新最小值

D之后最小值是B->不更新最小值

E之后最小值是D更新最小值

总结就是,升则更新(pop)降则不更新,但是得记录(入栈)

9be8f08ccf12fa8aa654fc7282986c8b.png

大概过程

e562e6f97f30f160797ff4194dc9531a.png

下面代码:

public 

下一个题更是巧妙,虽然是前面的拓展

看一个无序数组中是否存在这样的序列

使得 i< j < k 且 a[i]<a[j]<a[k]

方法:栈

结构双向队列

先扫找到一个后面的数比前面的数大的情况

我们要找到一个数,他到后面有一个比他大的数,并且他的前面有一个比他小的数。

方法:

双向队列。

从后王前入队列,初始化入队,

如果比队尾元素小,入队,如果size等于3则返回true,否则继续

如果比队头大则替换队头不替换队尾,

如果比队头小,但是比队尾大,则替换队尾,

8ba7dba7ec7dec9325c1174d57935b34.png
public 

第三个是数组的妙用:实际和队列很像,只是由于替换这一步,队列不方便,所以就用数组表示了。

求一个序列中最长的递增子序列:

方法:数组比较。下面链接是原文

Longest Increasing Subsequence Size (N log N) - GeeksforGeeks​www.geeksforgeeks.org
9472d251bbcfd648c67faad260d3f874.png

比如序列 129045678

ans={1};

2>1 ans={1,2}

9>2 ans={1,2,9}

0<9->0<2->0<1 ans={0,2,9}

4<9->4>2->ans={0,2,4}

ans={0,2,4,5,6,7,8}

最后返回ans的size就好。

 public static int solve(int[] a){
        if(a.length==0)
            return 0;
        List<Integer> ans=new ArrayList<>();
        ans.add(a[0]);
        for(int i=1;i<a.length;i++){
            if(a[i]>ans.get(ans.size()-1)){
                ans.add(a[i]);
            }else{

                int loc=upper_bound(ans,a[i],0,ans.size()-1);
                //去重
                if(loc==0||(loc-1>=0&&ans.get(loc-1)!=a[i]))
                ans.set(loc,a[i]);
            }
        }

        return ans.size();
    }

    //find the loc
    public static int upper_bound(List<Integer> ans,int target,int l,int r){
        while(l<r){

            int mid=l+(r-l)/2;
            if(ans.get(mid)>target){
                r=mid;
            }else{
                l=mid+1;
            }

        }
        return l;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值