Leetcode周赛--2021.8.15

emmm,昨天忘记今早实验室上午断电,没带电脑回宿舍,实验室没电自然也打不开指纹锁,所以在得知断电之后,直接取消报名睡大觉zzz
下午补上今早的周赛题解,emm总体还是比较简单的,前三道都挺基础的,第四道还是没看。。。

第一题—5843. 作为子字符串出现在单词中的字符串数目

Leetcode周赛--2021.8.15_第1张图片
Leetcode周赛--2021.8.15_第2张图片

Leetcode周赛--2021.8.15_第3张图片

思路

判断patterns数组内的元素有多少个是字符串word的子字符串,因为求的是连续的子字符串而不是子序列,所以直接使用String自带的contains()函数即可,只要返回true就计数器加一
时间复杂度 O ( n ) O(n) O(n),n为数组patterns的元素数量
空间复杂度 O ( 1 ) O(1) O(1),只使用了ans进行计数

代码

class Solution {
    public int numOfStrings(String[] patterns, String word) {
        int ans = 0;
        for (int i=0;i<patterns.length;i++)
        {
            if (word.contains(patterns[i]))
                ans++;
        }
        return ans;
    }
}

第二题

Leetcode周赛--2021.8.15_第4张图片
Leetcode周赛--2021.8.15_第5张图片

Leetcode周赛--2021.8.15_第6张图片

思路

需要注意的是,重新排列后的数组每连续三个元素都满足 ( n u m s [ i + 1 ] + n u m s [ i − 1 ] ) ≠ ( 2 × n u m s [ i ] ) (nums[i+1]+nums[i-1]) \neq (2 \times nums[i]) (nums[i+1]+nums[i1])=(2×nums[i]),所以会想到,如果先将数组元素进行排列,然后使每一个较大元素都位于两个较小元素之间,因此构成了“大小大小大…”或“小大小大…”的形式,两个较小数 M I N 1 < M I N 2 MIN_1MIN1<MIN2的平均值 a v g 1 avg_1 avg1一定位于区间 M I N 1 < a v g 1 < M I N 2 < M A X MIN_1MIN1<avg1<MIN2<MAX不会等于较大的值,而两个较大值 M A X 1 < M A X 2 MAX_1MAX1<MAX2的平均值 a v g 2 avg_2 avg2,也一定位于两个较大值之间 M I N < M A X 1 < a v g 1 < M A X 2 MINMIN<MAX1<avg1<MAX2,所以按照这样排列的数组一定满足题目要求。

算法步骤:

  1. 首先检测当前的数组是否满足条件,满足条件的话直接返回原数组即可;
  2. 如果不满足条件,首先对数组进行排序(升序或降序都可以,分别对应“大小大小大…”、“小大小大…”两种形式,都可以满足题目要求),然后在结果数组中,按照一个当前最大值,一个当前最小值的顺序穿插着填充;
  3. 这样填充的结果数组一定满足题目要求,所以可以直接进行返回;

时间复杂度 O ( n ) O(n) O(n),因为需要对数组进行排序和遍历,所以时间复杂度为 O ( n ) O(n) O(n),n为数组nums的长度;
空间复杂度 O ( n ) O(n) O(n),因为需要一个与数组nums完全一致的数组存储结果;

代码–写复杂了,其实checkResult函数可以直接嵌入主函数中,因为只使用了一次。。

class Solution {
     public int[] rearrangeArray(int[] nums) {

        //检查原有数组是否满足条件,满足的话直接返回原数组即可
        if (checkResult(nums))
            return nums;

        int ans[] = new int[nums.length];

        Arrays.sort(nums);
        int l=0,r=nums.length-1;
        int index = 1;
        while (index<=nums.length)
        {
            if (index%2!=0)
                ans[index-1] = nums[l++];
            else
                ans[index-1] = nums[r--];
            index++;
        }

        return ans;
    }

    public boolean checkResult(int[] nums)
    {
        int flag = 0;
        for (int i=1;i<nums.length-1;i++)
        {
            if (nums[i]*2 == (nums[i-1]+nums[i+1]))
            {
                flag=1;
                break;
            }
        }
        if (flag==0)
            return true;
        return false;
    }
}

第三题

Leetcode周赛--2021.8.15_第7张图片
Leetcode周赛--2021.8.15_第8张图片
Leetcode周赛--2021.8.15_第9张图片

思路

emmm,一个找规律的数学题,通过给出的示例,以及对后续输入的推算,可以得到如下规律:

当输入为p时,对对应的nums数组内的元素进行任意次交换,在不存在0的情况下,最终一定可以凑成如下形式:

r e s u l t = 2 p − 1 × ( 2 p − 1 − 1 ) 2 p − 2 − 1 result = 2^{p-1} \times {(2^{p-1}-1)}^{2^{p-2}-1} result=2p1×(2p11)2p21

各位可以自行推导一下 p = 4 p=4 p=4的情况进行验证,因此可以得到如下的算法:

  1. 分别获取 x = 2 p − 1 x=2^{p-1} x=2p1 y = ( 2 p − 1 − 1 ) y={(2^{p-1}-1)} y=(2p11) c o u n t = 2 p − 2 − 1 count={2^{p-2}-1} count=2p21,因为当p=60时,x、y、count的值都会超出int的范围,所以这里使用long(可以存储 [ − 2 63 , ( 2 63 − 1 ) ] [-2^{63},(2^{63}-1)] [263,(2631)]的数据)进行存储,并将x和y分别对 1 e 9 + 7 1e9+7 1e9+7进行取余,注意不能对count进行取余
  2. 计算最终的答案,因为数值可能非常大,所以每一步都要对 1 e 9 + 7 1e9+7 1e9+7进行取余;

时间复杂度 O ( n ) O(n) O(n) n = c o u n t + 1 n= \sqrt{count}+1 n=count +1
空间复杂度 O ( 1 ) O(1) O(1),因为只需要几个变量存储数值即可

代码

class Solution {
    public int minNonZeroProduct(int p) {
        int mod = (int)1e9+7;

        long x = ((long) Math.pow(2,p)-1)%mod;
        long y = (x-1)%mod;

        long ans = x;
        long count = ((long) Math.pow(2,p-1))-1;
        
        while (count>0)
        {
            if ((count&1)==1)
                ans = (ans * y)%mod;
            y = (y * y)%mod;
            count>>=1;
        }
        return (int)ans;
    }
}

你可能感兴趣的:(Java学习,Leetcode周赛,leetcode,java)