leetcode一周题解(20220404-20220410)

#2207 字符串中最多数目的子字符串

前缀和加求和问题(贪心的思想),注意pattern中pattern[0]==pattern[1]这种个情况

class Solution {
    public long maximumSubsequenceCount(String text, String pattern) {
        int ctf=0,ctl=0;//ctf统计pattern[0]的个数,ctl统计pattern[1]的个数
        char[]array=pattern.toCharArray();
        char a=array[0],b=array[1];
        long ans=0;
        char[]t=text.toCharArray();
        for(char i:t){
            if(i==a) ctf++;
            if(i==b){//当i=b时,就有ctf个组合方式。就是对每个b加上当前a的个数
                ctl++;//记录b的个数,为了最后比较a的个数和b的个数,添加能产生最大的那个
                ans+=ctf;
            }
        }
        return a==b?ans:ans+Math.max(ctf,ctl);

    }
}
#1109 航班预订统计

首先我想了2分钟感觉可以直接模拟暴力求解,就没往前缀和方面想(的确,脑子里也没有差分数组相关知识!)

class Solution {
    public int[] corpFlightBookings(int[][] bookings, int n) {
        int[]ans=new int[n];
        for(int i=0;i<bookings.length;i++){
            int start=bookings[i][0]-1;
            int end=bookings[i][1]-1;
            int id=bookings[i][2];
            for(int j=start;j<=end;j++){ans[j]+=id;}
        }
        return ans;

    }
}

前缀和加差分数组(前后两个变量的差值组成的数组)要搞清差分数组的性质,差分数组其实你在start的地方加上变量一次,后边的因为累加的原因都加上了这个变量,但end+1的地方没有加变量,所以要在end+1的地方减去变量一次!

class Solution {
    public int[] corpFlightBookings(int[][] bookings, int n) {
        int[]res=new int[n];
        for(int[]booking:bookings){
            res[booking[0]-1]+=booking[2];//差分数组开头加上变量
            if(booking[1]<n){
                res[booking[1]]-=booking[2];//end+1要减去这个变量(因为这个变量只加在start到end中)
            }
        }
        for(int i=1;i<n;i++){
            res[i]+=res[i-1];
        }
        return res;

    }
}

#6035 选择建筑的方案数

首先想法是,统计每个位置前后0的个数和1的位数,因为只可能是(‘010’或‘101’)这两种情况。

一开始是想用两个前缀和统计0和1,后来才发现这个建筑类型只有0和1两种类型其实,统计一个0的数量,完全可以通过长度相减知道1的个数(非‘0’即‘1’)代码如下;

class Solution {
    public long numberOfWays(String s) {
        int n=s.length();
        long ways=0L;
        int[]prevZero=new int[n];
        prevZero[0]=s.charAt(0)=='0'?1:0;
        for(int i=1;i<n;i++){
            prevZero[i]=prevZero[i-1]+(s.charAt(i)=='0'?1:0);//统计0的前缀和
        }
        for(int i=1;i<n-1;i++){
            if(s.charAt(i)=='0'){
                ways+=(i-prevZero[i-1])*(n-1-i-(prevZero[n-1]-prevZero[i]));//第i位置1的个数就是i-0的前缀和
            }else{
                ways+=prevZero[i-1]*(prevZero[n-1]-prevZero[i]);
            }
        }
        return ways;

    }
}

然后看到了评论区一个十分巧妙的方法,其实就是顺序遍历一遍就可以解决的(不要太想复杂了),其实就是两种情况‘010’和‘101’,下边的方法可以用来找任意abc的顺序,代码如下:

class Solution {
    public long numberOfWays(String s) {
        char[]chars=s.toCharArray();
        char[]char1={'0','1','0'};//两种情况
        char[]char2={'1','0','1'};
        return help(chars,char1)+help(chars,char2);
    }
    public long help(char[]chars,char[]goal){
        long a=0,b=0,c=0;//a统计前边等于目标第一位的个数,b统计当前等于第二位的个数,c也就是一共能形成goal的个数
        for(int i=0;i<chars.length;i++){
            if(chars[i]==goal[0]) a++;
            if(chars[i]==goal[1]) b+=a;//乘法原理
            if(chars[i]==goal[2]) c+=b;
        }
        return c;
    }
}

#1371 每个元音包含偶数次的最长子字符

奇偶状态想到异或来进行状态判断,前缀和获取状态量。

class Solution {
    public int findTheLongestSubstring(String s) { 
        int[]pos=new int[1<<5];//5个元音字母可以用5位二进制数来储存他们的状态
        Arrays.fill(pos,-1);
        pos[0]=0;
        int state=0,max=0;
        for(int i=0;i<s.length();i++){
            char c=s.charAt(i);
            if(c=='a'){
                state^=(1<<0);
            }else if(c=='e'){
                state^=(1<<1);
            }else if(c=='i'){
                state^=(1<<2);
            }else if(c=='o'){
                state^=(1<<3);
            }else if(c=='u'){
                state^=(1<<4);
            }
            if(pos[state]>=0) max=Math.max(max,i+1-pos[state]);
            else{
                pos[state]=i+1;
            }
        }
        return max;

    }
}
#1248 统计「优美子数组」

本质是奇数和为k的子数组个数,偶数直接无视掉

class Solution {
    public int numberOfSubarrays(int[] nums, int k) {
        int n=nums.length;
        int[]odd=new int[n+2];
        odd[0]=-1;
        int cnt=0,ans=0;
        for(int i=0;i<n;++i){
            if((nums[i]&1)!=0){
                odd[++cnt]=i;
            }
        }
        odd[++cnt]=n;
        for(int i=1;i+k<=cnt;++i){
            ans+=(odd[i]-odd[i-1])*(odd[i+k]-odd[i+k-1]);
        }
        return ans;

    }
}
#528 按权重随机选择

前缀和+二分查找。

#209 长度最小的子数组

滑动窗口简单问题。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int i=0,sum=0,len=0;
        for(int j=0;j<nums.length;j++){
            sum+=nums[j];
            while(sum>=target){
                len=len==0?j-i+1:Math.min(len,j-i+1);
                sum-=nums[i++];
            }
        }
        return len;

    }
}

这周状态很不好,中途因为自己线性代数方面知识并不好,做了好几天矩阵题都很吃劲,所以这周也就放了前半周做的题,周五从早上5.起来就开始自暴自弃打游戏打到晚上11.,晚上在母亲的劝说下觉得自己路还很长不能摆烂,但是星期六到今天头巨痛,打游戏注意力高度集中也不出去走动导致了精神有点恍惚,一直到今天下午都没缓过来,希望我未来打游戏不是去把它当成逃避摆烂的手段,而是真正的娱乐自己。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值