Leetcode--2021.6.20周赛

emmm,今天的周赛还是很菜,今天还是很粗心,很急躁,不知道什么时候才能彻底改掉这些毛病。今天的题其实比之前的比赛都要简单,至少看的明白,有思路,但是自己太急躁,没读懂题意就瞎写,导致在第一个题花费了大量时间,根本没时间做后面两个。。。以后要注意克服自己急躁的情绪了,最近太浮躁了。。

第一题

在这里插入图片描述

思路

第一题其实非常简单,后面想明白后恨不得给自己一个大嘴巴子。。。因为判断的是字符串中最大的奇数,所以直接从字符串的右侧,一个一个的检测当前所指向的数字是否是奇数即可,其实没有那么多的花里胡哨,最开始做题的时候自己想的过于复杂。。。
直接看代码吧。

代码

class Solution {
    public String largestOddNumber(String num) {
        int r = num.length()-1;
        while (r>=0)
        {
            if ((num.charAt(r)-'0')%2==0)
                r--;
            else
                return num.substring(0,r+1);
        }
        return "";
    }
}

第二题

在这里插入图片描述

思路

这一题也很简单,唯一要注意的就是,当开始时间的小时数和结束时间的小时数相等时,需要进行判断这是一天还是两天(第一次提交没注意,就被坑了),其他的就没啥了,按部就班做就行。
算法步骤:

  1. 开始时间结束时间的字符串中分别截取对应的小时数h1、h2和分钟数m1、m2
  2. 分情况开始讨论:如果h1<h2证明在同一天内,直接ans=(h2-h1-1)*4;ans += (60-m1)/15;ans+=m2/15即为答案;如果h1>h2证明不在同一天内,直接ans=(24-h1-1+h2)*4;ans += (60-m1)/15;ans+=m2/15即为答案;如果h1=h2需要分情况进行讨论——如果m1<m2证明在同一天内,根据m1和m2的值计算得到ans即可;如果m1>m2证明不在同一天内,ans = 23 * 4; ans += (60-m1)/15; ans += m2/15即可。

代码

public int numberOfRounds(String startTime, String finishTime) {
        int h1 = Integer.parseInt(startTime.substring(0,2)) ;
        int m1 = Integer.parseInt(startTime.substring(3,5)) ;
        int h2 = Integer.parseInt(finishTime.substring(0,2)) ;
        int m2 = Integer.parseInt(finishTime.substring(3,5)) ;

        int ans = 0;

        if (h1 < h2){
            ans = (h2-h1-1)*4;
            ans += (60-m1)/15;
            ans += m2/15;
        }
        if (h1 > h2)
        {
            ans = (24-h1-1 + h2)*4;
            ans += (60-m1)/15;
            ans += m2/15;
        }
        if (h1==h2)
        {
            if (m1<m2)
            {
                if (m1<=15)
                    ans = (m2-15)/15;
                if (m1 > 15 && m1 <= 30)
                    ans = (m2-30)/15;
                if (m1>30 && m1<=45)
                    ans = (m2-30)/15;
            }
            if (m2 < m1)
            {
                ans = 23 * 4;
                ans += (60-m1)/15;
                ans += m2/15;
            }
        }
        return ans>=0?ans:0;
    }

第三题

在这里插入图片描述
在这里插入图片描述

思路

没来得及看。。以后有时间再来补充

代码

第四题

在这里插入图片描述
在这里插入图片描述

思路

因为涉及的数据量比较大,又涉及到区间的重复查询,所以采用类似于前缀和等预处理方法效果比较好。

最开始因为示例给的比较特殊再加上没有理解题意,我对相邻的两个值的差绝对值进行了预处理,然后查询时直接在ans中查询即可,因为示例给的比较特殊,所以示例测试没有任何问题,提交后才发现是是区间内任意两个元素的差绝对值的最小值。。。太坑人了

因为时间不够了,所以没有想到新的预处理方法,以后有时间再来补充。。。

--------------------------2021.6.30更新--------------------------
之前的处理方法有问题,在学习大佬们的代码后,学会了新的预处理方法,在此记录一下。
使用一个二维数组pre[i][j]存储数组nums的前i个元素中值为j的个数,其中 1 ≤ i ≤ n u m s . l e n g t h , 1 ≤ j ≤ 100 1\le i \le nums.length,1\le j \le 100 1inums.length1j100,为了方便统一处理,所以将其范围均扩充到0。
因为数组nums中的值的范围为 1 ≤ n u m s [ i ] ≤ 100 1 \le nums[i] \le 100 1nums[i]100,数组queries最多含有20,000个元素对,所以可以对每个元素对依次从1-100进行判断,计算量最大为2,000,000,不超过1e7,所以不会超时。

代码

class Solution {
    public int[] minDifference(int[] nums, int[][] queries) {
        int len = nums.length;
        int row = queries.length;

        //存储前i个元素中分别包含多少个1-100的元素
        int[][] pre = new int[len+1][101];
        for (int i = 0;i<len;i++)
        {
            for (int j=0;j<101;j++)
                pre[i+1][j] = pre[i][j];//每一个都是在上一个的基础上进行累加
            pre[i+1][nums[i]]++;
        }

        int[] ans = new int[row];

        for (int i=0;i<row;i++)
        {
            int l=queries[i][0], r = queries[i][1];//分别获取元素对中左右边界
            int minValue = Integer.MAX_VALUE, last = -1;//last存储的是上一个出现的值,因为是从1开始进行遍历,想要得到最小的差值,绝对是相邻两个值的差值
            for (int j=1;j<101;j++)//因为nums的值的范围是1-100,所以直接逐个进行判断
            {
                if (pre[l][j] < pre[r+1][j])//一旦右边界中包含该元素的数量大于左边界,证明其中出现了对于的j值
                {
                    if (last != -1)//因为last对每一个元素对都会初始化为-1,一旦last不为-1,证明元素对所指向的区间长度至少为2
                        minValue = Math.min(minValue, j-last);//获取当前范围内的最小值
                    last = j;
                }
            }
            if (minValue == Integer.MAX_VALUE)//如果minValue的值没有变化,证明当前元素对所指向区间内的所有值均相等,按照题目要求结果为-1
                minValue = -1;
            ans[i] = minValue;
        }


        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值