在其中一个HackerRank Java挑战中,存在一个问题,定义为:
问题
我们定义以下术语:
Lexicographical Order,也称为字母或字典顺序,按如下顺序排列字符:A< B< ...< Y< Z< a< b ......< y< ž
字符串的子字符串是字符串中连续的字符块。例如,abc的子串是a,b,c,ab,bc和abc。
给定一个字符串 s 和一个整数 k ,完成 函数,以便它找到按字典顺序最小和 最大子串长度 k 。
这是我的(不完全正常)解决方案:
我的代码
import java.util.*;
public class stringCompare {
public static String getSmallestAndLargest(String s, int k) {
String smallest, largest, temp;
/* Initially, define the smallest and largest substrings as the first k chars */
smallest = s.substring(0, k);
largest = s.substring(0, k);
for (int i = 0; i <= s.length() - k; i++) {
temp = s.substring(i, i + k);
for (int j = 0; j < k; j++) {
/* Check if the first char of the next substring is greater than the largest ones' */
if (temp.charAt(j) > largest.charAt(j)) {
largest = s.substring(i, i + k);
break;
}
/* Check if the first char of the next substring is less than the smallest ones' */
else if (temp.charAt(j) < smallest.charAt(j)) {
smallest = s.substring(i, i + k);
break;
}
/* Check if the first char of the next substring is either equal to smallest or largest substrings' */
else if (temp.charAt(j) == smallest.charAt(j)
|| temp.charAt(j) == largest.charAt(j)) {
// If so, move to the next char till it becomes different
}
/* If the first of char of the next substring is neither of these (between smallest and largest ones')
skip that substring */
else {
break;
}
}
}
return smallest + "\n" + largest;
}
public static void main(String[] args) {
String s;
int k;
try (Scanner scan = new Scanner(System.in)) {
s = scan.next();
k = scan.nextInt();
}
System.out.println(getSmallestAndLargest(s, k));
}
}
根据HackerRank,此代码在6个案例中有2个失败。一个如下:
ASDFHDSFHsdlfhsdlfLDFHSDLFHsdlfhsdlhkfsdlfLHDFLSDKFHsdfhsdlkfhsdlfhsLFDLSFHSDLFHsdkfhsdkfhsdkfhsdfhsdfjeaDFHSDLFHDFlajfsdlfhsdlfhDSLFHSDLFHdlfhs
30
预期输出为:
ASDFHDSFHsdlfhsdlfLDFHSDLFHsdl
sdlkfhsdlfhsLFDLSFHSDLFHsdkfhs
但是我变成了:
DFHSDLFHDFlajfsdlfhsdlfhDSLFHS
sdlkfhsdlfhsLFDLSFHSDLFHsdkfhs
在调试模式下,我发现最小的子串是正确的,直到第67次迭代(i)。我不知道为什么它会在那一步发生变化,但确实如此。
有人可以帮我吗?
谢谢!
答案 0 :(得分:3)
问题在于您在单个循环中尝试比较最大值和最小值。更具体地说,这条线存在问题:
else if (temp.charAt(j) == smallest.charAt(j)
|| temp.charAt(j) == largest.charAt(j)) {
// If so, move to the next char till it becomes different
}
您可能希望继续j
上的循环来检测最小的子字符串,但是在j
上跳出循环以检测最大的子字符串。这就是为什么两个检查应该彼此独立完成。
要考虑的几个小问题:
largest = s.substring(i, i + k)
,因为它与largest = temp
相同;同样适用于smallest
。compareTo
为您执行词典比较。基本上,你的程序可以简化为:
largest = smallest = s.substring(0, k);
for (int i = 1 ; i <= s.length() - k; i++) {
temp = s.substring(i, i + k);
if (temp.compareTo(largest) > 0) {
largestt = temp;
} else if (temp.compareTo(smallest) < 0) {
smalles = temp;
}
}
请注意,循环可以从i = 1
开始,因为您使用s.substring(0, k)
来初始化largest
和smallest
。
答案 1 :(得分:2)
到目前为止,您无法将某个子字符串与最小的子字符串和最大的子字符串进行比较。特别是条件
temp.charAt(j) == smallest.charAt(j)
|| temp.charAt(j) == largest.charAt(j)
有问题。举个例子
smallest ad
largest bx
temp bc
在此示例中,您的代码将得出结论:bc小于广告
答案 2 :(得分:1)
我提出了一个简单的优化:快速查看第一个字符。
largest = smallest = s.substring(0, k);
for (int i = 1; i <= s.length() - k; i++) {
if (s.charAt(i) > largest.charAt(0) ){
largest = s.substring(i, i + k);
continue;
}
if (s.charAt(i) < smallest.charAt(0) ){
smallest = s.substring(i, i + k);
continue;
}
if (s.charAt(i) == largest.charAt(0) ){
String temp = s.substring(i, i + k);
if( temp.compareTo(largest) > 0) {
largest = temp;
continue;
}
}
if (s.charAt(i) == smallest.charAt(0) ){
String temp = s.substring(i, i + k);
if( temp.compareTo(smallest) < 0) {
smallest = temp;
}
}
}
例如,比较从222下降到14。