leetcode-卡特兰数-括号所有出栈序列-761. 特殊的二进制序列-179最大数

出栈序列有多少种?_凛冬烈焰的博客-CSDN博客_出栈序列

离散数学目录整理 - waryan - 博客园

AB入栈;f(2) = f(0)*f(1)+f(1)*f(0)=2

(()) -----()()

ABCD

按照“第一个入栈的元素,在出栈序列中的位置”作为分类手段。

A在第一个那么就是()入出,额外的f(0)

那么此时剩下的就是f(3)

第二个出,(())那么剩下的就是f(2)

第三个-((()))or( ( ) ( ) )   也就是f(2)除开必须第三个的A,剩下的是f(1)

所以就是f(0)Af(3)-f(1)Af(2)-f(2)Af(1)-f(3)Af(0)

这就是所有出栈排列

用母函数推卡特兰数通项公式 - 知乎

\frac{1}{n+1}C^n_{2n}

f(n)=\frac{4n-2}{n+1}f(n-1)

注意先用4n-2乘以f(n-1)再除以,不然损失精度

有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少种方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈):

https://leetcode.cn/problems/special-binary-string/

761. 特殊的二进制序列

class Solution {
    public String makeLargestSpecial(String s) {
        if (s.length() <= 2) {
            return s;
        }
        int cnt = 0, left = 0;
        List<String> subs = new ArrayList<String>();
        for (int i = 0; i < s.length(); ++i) {
            if (s.charAt(i) == '1') {
                ++cnt;
            } else {
                --cnt;
                if (cnt == 0) {
                    subs.add("1" + makeLargestSpecial(s.substring(left + 1, i)) + "0");
                    left = i + 1;
                }
            }
        }

        Collections.sort(subs, (a, b) -> b.compareTo(a));
        StringBuilder ans = new StringBuilder();
        for (String sub : subs) {
            ans.append(sub);
        }
        return ans.toString();
    }
}

179. 最大数

class Solution {
    public String largestNumber(int[] nums) {
        PriorityQueue<String> heap = new PriorityQueue<>((x, y) -> (y + x).compareTo(x + y));
        for(int x: nums) heap.offer(String.valueOf(x));
        String res = "";
        while(heap.size() > 0) res += heap.poll();
        if(res.charAt(0) == '0') return "0";
        return res;
    }
}
PriorityQueue<Integer> heap3 = new PriorityQueue<>(Comparator.reverseOrder());

https://www.jianshu.com/p/81e5c3e88fc6

因为最小堆里面字符串顺序,3是小于30但是大于10,但是我们想要的是330而不是303

同理3-31, 3-32, 

也就是字典顺序不行了,那么其实反正目的是比较任意的,直接拼在一起比较

字符串:(x+y)->(y+x).compareTo(x+y)

x,y---3,32, 现在323<332比较--> x<y,3<32

所以顺序是3,32,31,30,交换x,y顺序就变成最小堆了,

这样子排序然后拼接在一起就是最大数了。

class Solution {
    public String largestNumber(int[] nums) {
        Queue<String> pq = new PriorityQueue<>((x,y)->((y+x).compareTo(x+y)));
       for(int each: nums){
           pq.offer(String.valueOf(each));
       }
        StringBuffer str = new StringBuffer();
        while(!pq.isEmpty()){
      
            str.append(pq.poll());
        }

        if(str.charAt(0)=='0') return "0";
        return str.toString();

    }
}

注意{0,0},原数据和目标数据都不存在00,最多0,

 Collections.sort(list,(x,y)->x.compareTo(y));

//
 list.sort((x,y)->x.compareTo(y));

两种调用排序

1 10 1100 0---这个是不能拆的最小的特殊的序列,

如何判断是否是不可以分割的,那就是()一个完整的括号,所以就是数1和0,一旦是抵消就是不可以分割的

比如10,1100,110100

因此第一步就是将一个字符串分割成这样的子串,然后按照字典顺序排序即可

然后每个字串自己本身也是除开首尾,内部的

101100---这样的根本不满足最小分割,因为直接可以10,1100,因此也就是说,

2: 10

4,1010不会出现,最多1100

6,10 10 10,10  1100,1100 10统统不行,可以再分,110100,111000就可以

110100不可以再分,意味着第二也必须是1,那么因为首位必须是一对10,那么除开10,还剩1010,或者1100,那么如果是1010,最后就是分成10,10,如果是1100就是分成1-10-0

遇到1 count++,遇到0 count--

List<String> subs = new ArrayList<>();
int left=0,count=0;

for(int i=0;i<str.length();++i){
    if(str.charAt(i)==1){
        ++count;
    }else{
        --count;
        if(count==0){
            subs.add("1"+makeLargestSpecial(str.substring(left+1,i)+"0");

        left = i+1;
        }
    }
}



            

substring没有大写,且前闭后开

这样子就完成了所有分割,然后排序并且结合

Collections.sort(subs,(x,y)->y.compareTo(x));
StringBuffer ans = new StringBuffer();
for(String each: subs){
    ans.append(each);
}

return ans.toString();

StringBuffer 需要转换成String

递归的初始条件就是10的时候以及110100---第一步分成10变成1-“”-0,也就是空集

所以

if(str.length()<=2){
    return str;
}
        subs.sort((x,y)->y.compareTo(x));
        StringBuffer ans = new StringBuffer();
        subs.forEach((each)->{
             ans.append(each);
        });

        return ans.toString();

sort有两种方式调用

forEach函数也可以直接使用;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值