[5.23]力扣周赛
一、5763. 哪种连续子字符串更长
给你一个二进制字符串
s
。如果字符串中由1
组成的 最长 连续子字符串 严格长于 由0
组成的 最长 连续子字符串,返回true
;否则,返回false
。
题解:
这题比较简单,直接采用双指针的方法过一遍就可以了,时间复杂度O(n)
public static boolean checkZeroOnes(String s) {
int one=0;
int zero=0;
int i=0;
int j=0;
while(i<s.length()){
int sum_one=0;
int sum_zero=0;
while (j<s.length()&&s.charAt(j)=='0') {
sum_zero++;
j++;
}
while (j<s.length()&&s.charAt(j)=='1') {
sum_one++;
j++;
}
one=Math.max(one,sum_one);
zero=Math.max(zero,sum_zero);
i=j;
}
System.out.println(one+" "+zero);
return one>zero;
}
二、5764. 准时到达的列车最小时速
给你一个浮点数
hour
,表示你到达办公室可用的总通勤时间。要到达办公室,你必须按给定次序乘坐n
趟列车。另给你一个长度为n
的整数数组dist
,其中dist[i]
表示第i
趟列车的行驶距离(单位是千米)。每趟列车均只能在整点发车,所以你可能需要在两趟列车之间等待一段时间。
- 例如,第
1
趟列车需要1.5
小时,那你必须再等待0.5
小时,搭乘在第 2 小时发车的第2
趟列车。返回能满足你准时到达办公室所要求全部列车的 最小正整数 时速(单位:千米每小时),如果无法准时到达,则返回
-1
。
题解一(超时):
采用暴力的方法,首先进行一个分类:
- 由于最短时间的话也算是一个小时,所以如果时间比数组的长度减一还要短的话,直接输出-1即可
- 如果时间比数组短但是又比n-1长的话,则只需要考虑数组中最大的数和最后的到达的时间的最大值即可
- 如果比数组长的话,则进行一个遍历来进行计算
public int minSpeedOnTime(int[] dist, double hour) {
int n=dist.length;
if(hour<=n-1) return -1;
int res=1;
int max=0;
for(int i:dist){
max=Math.max(i,max);
}
if(hour<=n){
//System.out.println((float)(Math.round((hour-n+1)*100))/100);
int temp= (int) Math.ceil(dist[n-1]/((float)(Math.round((hour-n+1)*100))/100));
//System.out.println(temp);
res=Math.max(max,temp);
return res;
}
else if(hour>n){
while(res<hour){
double temp=0;
for(int i=0;i<n-1;i++){
temp=temp+Math.ceil(dist[i]/(1.0*res));
if (temp>hour) break;
}
temp+=dist[n-1]/(1.0*res);
if(temp<=hour) break;
res++;
}
}
return res;
题解二:(遍历那里使用二分)
!!!过啦
class Solution {
public int minSpeedOnTime(int[] dist, double hour) {
int n=dist.length;
if(hour<=n-1) return -1;
int res=1;
int max=0;
for(int i:dist){
max=Math.max(i,max);
}
if(hour<=n){
int temp= (int) Math.ceil(dist[n-1]/((float)(Math.round((hour-n+1)*100))/100));
res=Math.max(max,temp);
return res;
}
else if(hour>n){
int mid=0;
int end=10000000;
while(res<=end){
mid = res+(end-res)/2;
double num = judge(mid, dist);
if(num<=hour){
end = mid-1;
}else if(num>hour){
res = mid+1;
}
}
return res;
}
return -1;
}
static double judge(int mid, int[] dist){
double ans = 0;
for(int i = 0;i<dist.length-1;i++){
int temp = dist[i]/mid;
if(dist[i]%mid!=0){
temp+=1;
}
ans+=temp;
}
ans += (dist[dist.length-1]/(mid*1.0));
return ans;
}
}
查看了大佬们的解析发现我想的有点复杂了,其实不需要进行分类,直接进行二分即可,下面列出来一个大佬的解析
作者:hxz1998
链接:https://leetcode-cn.com/problems/minimum-speed-to-arrive-on-time/solution/java-er-fen-fa-zhu-xing-zhu-shi-101ms528-zab8/
来源:力扣(LeetCode)
class Solution {
public int minSpeedOnTime(int[] dist, double hour) {
if (dist.length > Math.ceil(hour)) return -1;
// 搜索边界
int left = 1, right = Integer.MAX_VALUE;
while (left < right) {
int mid = left + (right - left) / 2;
// 如果以 mid 速度可达,那么就尝试减小速度
if (check(dist, hour, mid)) right = mid;
// 否则就需要加了
else left = mid + 1;
}
return left;
}
private boolean check(int[] dist, double hour, int speed) {
double cnt = 0.0;
// 对除了最后一个站点以外的时间进行向上取整累加
for (int i = 0; i < dist.length - 1; ++i) {
// 除法的向上取整
cnt += (dist[i] + speed - 1) / speed;
}
// 加上最后一个站点所需的时间
cnt += (double) dist[dist.length - 1] / speed;
return cnt <= hour;
}
}
三、5765. 跳跃游戏 VII
给你一个下标从 0 开始的二进制字符串
s
和两个整数minJump
和maxJump
。一开始,你在下标0
处,且该位置的值一定为'0'
。当同时满足如下条件时,你可以从下标i
移动到下标j
处:
i + minJump <= j <= min(i + maxJump, s.length - 1)
且s[j] == '0'
.如果你可以到达
s
的下标s.length - 1
处,请你返回true
,否则返回false
。
题解一:
采用dp动态规划的方法,从前往后面遍历,到达一个0的地方的时候就查看前面在[j-maxJump,j-minJump]的数组中是否含有dp[m]=1的值,有的话将dp[j]设置为一。
但是最后一个用例没有过
public static boolean canReach(String s, int minJump, int maxJump) {
int[] dp=new int[s.length()];
dp[0]=1;
for(int i=1;i<s.length();i++){
if(s.charAt(i)=='0'){
int left=i-maxJump;
int right=i-minJump;
if(left<0&&right<0) continue;
left=Math.max(left,0);
right=Math.max(right,0);
for(int m=left;m<=right;m++){
if(dp[m]==1){
dp[i]=1;
break;
}
}
}
}
System.out.println(Arrays.toString(dp));
return dp[s.length()-1]==1;
}
改进之后发现需要从前面进行扫描,不然的事件复杂度会超
public boolean canReach(String s, int minJump, int maxJump) {
int[] dp=new int[s.length()];
dp[0]=1;
for(int i=0;i<s.length();i++){
if(dp[i]==0) continue;
for(int j=i+minJump;j<=i+maxJump&&j<s.length()&&dp[j]==0;j++){
dp[j]=s.charAt(j)=='0'?1:0;
}
}
System.out.println(Arrays.toString(dp));
return dp[s.length()-1]==1;
}
之后看大佬们的解答,将我那个的遍历的判断改成了采用一个前缀树进行判断。