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 "";
}
}
第二题
思路
这一题也很简单,唯一要注意的就是,当开始时间的小时数和结束时间的小时数相等时,需要进行判断这是一天还是两天(第一次提交没注意,就被坑了)
,其他的就没啥了,按部就班做就行。
算法步骤:
- 从
开始时间
和结束时间
的字符串中分别截取对应的小时数h1、h2
和分钟数m1、m2
; - 分情况开始讨论:如果
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
1≤i≤nums.length,1≤j≤100,为了方便统一处理,所以将其范围均扩充到0。
因为数组nums
中的值的范围为
1
≤
n
u
m
s
[
i
]
≤
100
1 \le nums[i] \le 100
1≤nums[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;
}
}