[英]Issue with Time Calculation in Java
在筛选测试中,我被要求编写一个程序来获得一天中可用的最大空闲时间。
例如:
输入: “10:00AM-12:30PM”,“02:00PM-02:45PM”,“09:10AM-09:50AM”
预计 Output: 01:30
这些时间范围可能不按递增顺序排列。
对于这个问题,我尝试在 java 中编写一个小代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
public class TimeDiff {
public static void main(String[] args) throws NullPointerException {
String accStr = null;
System.out.println("Enter day time entries : ");
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
accStr = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
String unQuoted = accStr.replace("\"", "");
String[] inputSplit = unQuoted.split(",");
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("hh:mma");
Map<LocalTime, LocalTime> timeMap = new TreeMap<>();
for (String x : inputSplit) {
String[] furtherSplit = x.split("-");
timeMap.put(LocalTime.parse(furtherSplit[0], dateTimeFormatter), LocalTime.parse(furtherSplit[1], dateTimeFormatter));
}
Iterator iterator = timeMap.entrySet().iterator();
List<Long> duration = new ArrayList<Long>();
LocalTime[][] convertedMaptoArray = new LocalTime[timeMap.size()][2];
int rowIndex = 0;
while (iterator.hasNext()) {
int colIndex = 0;
Map.Entry pair = (Map.Entry) iterator.next();
//System.out.println(pair.getKey() + " " + pair.getValue());
convertedMaptoArray[rowIndex][colIndex] = (LocalTime) pair.getKey();
convertedMaptoArray[rowIndex][colIndex+1]=(LocalTime)pair.getValue();
rowIndex++;
}
LocalTime previousRecordEndTime = null;
LocalTime currentRecordStartTime = null;
for(int i= 0; i<=convertedMaptoArray.length-1;i++)
{
currentRecordStartTime = convertedMaptoArray[i][0];
//System.out.println("current :" +currentRecordStartTime);
if(i>0){
previousRecordEndTime = convertedMaptoArray[i-1][1];
//System.out.println("Previous : " + previousRecordEndTime);
duration.add(ChronoUnit.MINUTES.between(previousRecordEndTime, currentRecordStartTime));
}
}
System.out.println("Longest duration : " + LocalTime.MIN.plus(Duration.ofMinutes(Collections.max(duration))).toString());
}
}
我被筛选了,但我对上面的代码有几个问题:
请帮忙。 提前致谢。
我认为你正在破坏 KISS(使事情过于复杂),同时混合了 2 个截然不同的职责:解析输入的职责和计算间隔的职责 - 你只对最短的时间感兴趣,因此存储所有内容没有必要。
输入是否假定为通过控制台输入的字符串?
我将其分解为以下方法:
// 01:00AM -> 60
private static int timeStringToMinutesFromMidnight(String time)
// 60 -> 01:00
private static String minutesToHoursAndMinutes(int minutes)
// 11:00AM-11:30AM -> 660 690 added to list
private static void parseInterval(String interval, List<Integer> minutes)
(在之前的编辑中,我有timeStringIntervalToMinutes
,但我误读了问题并且计算了错误的输出)。
您在这里不需要任何复杂的数据结构:一个简单的List
可以让您完成所需的一切。 对其进行排序比使用TreeMap
或TreeSet
更容易 - 是的,它们进行自己的排序,但在占用空间和访问速度方面也更重。
完整代码(导入java.util.*
和java.io.*
):
// 01:00AM -> 60
private static int timeStringToMinutesFromMidnight(String time) {
int hours = Integer.parseInt(time.substring(0,"hh".length()));
int minutes = Integer.parseInt(time.substring("hh:".length(), "hh:mm".length()));
boolean afternoon = time.substring("hh:mm".length()).equalsIgnoreCase("PM");
if (afternoon && hours != 12) {
hours += 12;
}
return hours * 60 + minutes;
}
// 60 -> 01:00
private static String minutesToHoursAndMinutes(int minutes) {
int hours = minutes / 60;
minutes = minutes % 60;
return String.format("%02d:%02d", hours, minutes);
}
// 11:00AM-11:30AM -> 660 690 added to list
private static void parseInterval(String interval, List<Integer> minutes) {
String[] parts = interval.split("-");
int start = timeStringToMinutesFromMidnight(parts[0]);
int end = timeStringToMinutesFromMidnight(parts[1]);
if (end < start) {
throw new IllegalArgumentException("interval " + interval + " has end<start");
}
minutes.add(start);
minutes.add(end);
}
// Input: "10:00AM-12:30PM","02:00PM-02:45PM","09:10AM-09:50AM"
// Expected Output: 01:30
public static void main(String ... args) {
List<Integer> endpoints = new ArrayList<>();
try (Scanner sc = new Scanner(System.in).useDelimiter("[,\"]+")) {
while (sc.hasNext()) {
parseInterval(sc.next(), endpoints);
}
}
if (endpoints.isEmpty()) {
System.out.println("No intervals found");
return;
}
// sort the endpoints (assuming that no intervals overlap, intervals will not be broken)
Collections.sort(endpoints);
int largest = -1;
for (int i=1; i<endpoints.size()-1; i+=2) {
largest = Math.max(largest, endpoints.get(i+1) - endpoints.get(i));
}
System.out.println(minutesToHoursAndMinutes(largest));
}
我建议:
Map
用于您的条目。 使用一对 class 或定义一个TimeRange
class 可以容纳两个LocalTime
对象。 然后收集这些。Map
,也不要使用原始的Map.Entry
。 参数化为Map.Entry<LocalTIme, LocalTime>
。 同样参数化你的迭代器。 (另一方面, new ArrayList<Long>()
中的类型参数是多余的;只是new ArrayList<>()
是常规的。)Long
用于持续时间。 只需在整个过程中使用Duration
class。 使用其compareTo
方法进行比较。Collections.max()
。 我会传递从Arrays.asList()
获得的列表,或者甚至更好,避免 arrays 并将持续时间专门保留在列表中。 然后当然是适当的Comparator
实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.