LeetCode第34场双周赛 题解

1、矩阵对角线元素的和
Description

给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。
请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。

Solution

简单模拟!

AC Code
class Solution {
public:
    int diagonalSum(vector<vector<int>>& mat) {
        int len=mat.size();
        int sum=0;
        for(int i=0;i<len;i++){
            sum+=mat[i][i];
        }
        for(int i=0;i<len;i++){
            sum+=mat[i][len-i-1];
        }
        if(len%2) sum-=mat[len/2][len/2];
        return sum;
    }
};
2、分割字符串的方案数
Description

给你一个二进制串 s (一个只包含 0 和 1 的字符串),我们可以将 s 分割成 3 个 非空 字符串 s1, s2, s3 (s1 + s2 + s3 = s)。
请你返回分割 s 的方案数,满足 s1,s2 和 s3 中字符 ‘1’ 的数目相同。
由于答案可能很大,请将它对 10^9 + 7 取余后返回。

Solution

加法原理和分步乘法原理!
全为0时用加法原理,利用高中组合与排列中的挡板法,相当于求一个累加,从0累加到 s.length()-2。
其他情况用分步乘法原理!分两步!

AC Code
class Solution {
public:
    int numWays(string s) {
        int num=0;//1的个数
        vector<int> v;
        for(int i=0;i<s.length();i++){
            if(s[i]=='1'){
                num++;
                v.push_back(i);
            }
        }
        if(num==0) {//全为0  求累加
            long long m1=s.length()-1;
            long long m2=s.length()-2;
            long long ans=m1*m2;
            ans/=2;
            int mod=1e9+7;
            ans%=mod;
            return int(ans);
        }
        if(num%3) return 0;
        int len=num/3;
        long long m1=v[len]-v[len-1];//分割s1和s2的方案数
        long long m2=v[2*len]-v[2*len-1];//分割s3和s2的方案数
        long long ans=m1*m2;//总方案数
        int mod=1e9+7;
        ans%=mod;
        return int(ans);
    }
};
3、删除最短的子数组使剩余数组有序
Description

给你一个整数数组 arr ,请你删除一个子数组(可以为空),使得 arr 中剩下的元素是 非递减 的。
一个子数组指的是原数组中连续的一个子序列。
请你返回满足题目要求的最短子数组的长度。

Solution

因为是删除一个子数组,所以应该是从两边向中间收缩,找到一个最短子数组。要求处理后是非递减的。所以首先从前往后找到第一个非递增的元素,即从前往后找到一个尽可能长的非递减子数组。从后往前找第一个非递减的元素,即从后往前找到一个尽可能长的非递减子数组。然后就可以定下左右界限了。然后再尽可能的从两边中截取更多的元素并且组成的子数组是非递减的。

AC Code
class Solution {
public:
    int findLengthOfShortestSubarray(vector<int>& arr) {
        int len=arr.size();
        int l=-1,r=len;
        for(int i=0;i<len-1;i++){//从前往后找到第一个非递增的元素
            if(arr[i+1]<arr[i]) {
                l=i;
                break;
            }
        }
        for(int i=len-1;i>0;i--){//从后往前找第一个非递减的元素
            if(arr[i-1]>arr[i]) {
                r=i;
                break;
            }
        }
        if(r==len||l==-1) return 0;//原数组就是非递减的
        int ans=max(l+1,len-r);//前面和后面两个非递减的子数组中较长数组的长度
        for(int i=0;i<=l;i++){
            int j=r;
            for(;j<len;j++){
                if(arr[j]>=arr[i]){//满足非递减
                    break;
                }
            }
            ans=max(ans,i+1+(len-j));//更新 非递减的子数组的最大长度
        }
        return len-ans;
    }
};

PS:希望对你有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值