Leetcode_2055_蜡烛之间的盘子_前缀和

一开始的思路是找到区间内第一个蜡烛和最后一个蜡烛,最后计算这两个蜡烛之间的盘子数量,当然超时了。
那么怎么去优化这两个步骤呢,第一个步骤我采取了记录蜡烛位置的方式,通过二分查找区间上下限,定位到第一个蜡烛和最后一个蜡烛的下标;第二个步骤我采取前缀和数组的方式,记录前i个元素中盘子的个数。

class Solution {
    public int[] platesBetweenCandles(String s, int[][] queries) {
        int m = queries.length;
        int[] ans = new int[m];
        int[] pre = new int[s.length()];
        List<Integer> list = new ArrayList<>();
        if(s.charAt(0) == '*') {
            pre[0] = 1; 
        } else {
            list.add(0);
        }
        for(int i = 1;i < s.length();i++) {
            if(s.charAt(i) == '*') {
                pre[i] = pre[i - 1] + 1; 
            } else {
                pre[i] = pre[i - 1]; 
                list.add(i);
            }
        }
        for(int i = 0;i < m;i++) {
            int st = Collections.binarySearch(list, queries[i][0]);
            if(st < 0) {
                st = -st - 1;
            }
            int ed = Collections.binarySearch(list, queries[i][1]);
            if(ed < 0) {
                ed = -ed - 2;
            }
            if(st <= ed) {
                ans[i] = pre[list.get(ed)] - pre[list.get(st)];
            }
        }
        return ans;
    }
}

看了题解后,第一个步骤的优化也可以使用前缀和

class Solution {
    public int[] platesBetweenCandles(String s, int[][] queries) {
        int m = queries.length;
        int n = s.length();
        int[] ans = new int[m];
        int[] pre = new int[n];
        // 该下标最左的一个蜡烛
        int[] left = new int[n];
        // 该下标最右的一个蜡烛
        int[] right = new int[n];
        if(s.charAt(0) == '*') {
            pre[0] = 1;
            left[0] = -1;
        } else {
            left[0] = 0; 
        }
        for(int i = 1;i < n;i++) {
            if(s.charAt(i) == '*') {
                pre[i] = pre[i - 1] + 1;
                left[i] = left[i - 1];
            } else {
                pre[i] = pre[i - 1]; 
                left[i] = i;
            }
        }
        
        if(s.charAt(n - 1) == '*') {
            right[n - 1] = -1;
        } else {
            right[n - 1] = n - 1; 
        }

        for(int i = n - 2;i >= 0;i--) {
            if(s.charAt(i) == '*') {
                right[i] = right[i + 1];
            } else {
                right[i] = i;
            }
        }
        

        for(int i = 0;i < m;i++) {
            int st = right[queries[i][0]];
            int ed = left[queries[i][1]];
            if(st == -1 || ed == -1) {
                ans[i] = 0;
            } else if(st <= ed) {
                ans[i] = pre[ed] - pre[st];
            }
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值