(Java)字母子字符串比较的结果是错误的
在这些HackerRank Java挑战中,有一个问题定义为: 问题 我们定义了以下术语:(Java)字母子字符串比较的结果是错误的,java,comparison,substring,alphabetic,Java,Comparison,Substring,Alphabetic,在这些HackerRank Java挑战中,有一个问题定义为: 问题 我们定义了以下术语: 字典顺序,也称为字母顺序或字典顺序,对字符的顺序如下:A
- 字典顺序,也称为字母顺序或字典顺序,对字符的顺序如下:A
- 字符串的子字符串是字符串中连续的字符块。例如,abc的子字符串是a、b、c、ab、bc和abc
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));
}
}
预期产出为:
ASDFHDSFHsdlfhsdlfLDFHSDLFHsdl
sdlkfhsdlfhsLFDLSFHSDLFHsdkfhs
但我的变成:
DFHSDLFHDFlajfsdlfhsdlfhDSLFHS
sdlkfhsdlfhsLFDLSFHSDLFHsdkfhs
在调试模式下,我发现最小的子字符串在第67次迭代(I)之前是正确的。我不知道为什么在那一步它会变成一个错误的,但它确实是这样
有人能帮我吗
谢谢 问题在于,您试图在单个循环中对最大值和最小值进行比较。更具体地说,这一行有问题:
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
上中断循环以检测最大的子字符串。这就是为什么这两项检查应该独立进行的原因
需要考虑的几个小问题:
- 您不需要编写
,因为它与max=s.substring(i,i+k)
相同;最小的max=temp
也是如此
- 您根本不需要嵌套循环
为您执行词典比较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;
}
}
最大=最小=s.子串(0,k);
对于(int i=1;i 0){
最大温度=温度;
}否则如果(温度比(最小)<0){
smalles=温度;
}
}
请注意,循环可以从
i=1
开始,因为您使用s.substring(0,k)
来初始化最大的和最小的您不能同时将某个子字符串与迄今为止最小的和迄今为止最大的子字符串进行比较。尤其是条件
temp.charAt(j) == smallest.charAt(j)
|| temp.charAt(j) == largest.charAt(j)
这是有问题的。例如
smallest ad
largest bx
temp bc
在本例中,您的代码将得出结论,bc小于ad。我建议进行一个简单的优化:快速查看第一个字符
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;
}
}
}
最大=最小=s.子串(0,k);
对于(int i=1;i最大.charAt(0)){
最大=s.子串(i,i+k);
继续;
}
if(s.charAt(i)<最小的s.charAt(0)){
最小=s.子串(i,i+k);
继续;
}
如果(s.charAt(i)=最大的s.charAt(0)){
字符串温度=s.子字符串(i,i+k);
如果(温度比(最大)>0){
最大值=温度;
继续;
}
}
如果(s.charAt(i)=最小的s.charAt(0)){
字符串温度=s.子字符串(i,i+k);
if(温度比(最小值)<0){
最小值=温度;
}
}
}
例如,比较从222下降到14。如果设置最大值,则不需要检查较小值=>else++并且循环应以i=1@laune谢谢你的评论!偏航。“我们现在应该开始考虑优化了吗?”SaidBuyukarslan说,当你一次比较两个字符串时,可能会出现这样的情况:你希望对其中一个字符串做出决定,然后继续进行另一个字符串。Henry给了你一个很好的例子:当你的temp
是“bc”
时,最大的是“bx”
,最小的是“ad”
,你要停止考虑“bc”
在第一次迭代后潜在的最小字符串,因为a
在b
之前。但是,由于最大的
从b
开始,迭代继续到第二个索引,在这一点上,算法错误地得出结论“bc
”小于“ad”
。我知道您这样做是一个练习,但作为提示,String
实现compareTo
,您可以使用它来获取最小或最大的字符串。这也是一个@hospotintrinsicandidate
,因此它通常也会表现得更好(我知道这些在线挑战有时会根据性能排名)。实际上,我直到现在才知道这种方法。谢谢你的建议。此外,我不再在乎那些规则了。这里的一些用户告诉我,HackerRank上的那些任务需要过时的方法来解决问题,就像你一样,太:)我正在尽可能多地学习。你的错误是,在位置I+j处,当当前字符串从s开始时,仍然等于到目前为止最小或最大的字符串,并且你遇到一个小于最大或大于最小的字符,你用当前字符串在s处重置这些字符。啊,现在我明白了为什么我的代码会崩溃。当它捕捉到相同的起始字母时,它会在以下字符中出现偏差。但我仍然想知道,对于这样的情况,同时进行双重比较是否是错误的,或者还有其他原因吗?这两种比较可能需要不同的长度。因此,将它们组合在一个循环中是没有意义的。(你仍然可以通过使用一些标志来指示比较何时完成,但这会使你的代码变得不那么明显)。嗯,边界条件,我猜,是的,我第一手就想到了相同的标志检查方法,但正如你所说的,它会使代码变得非常复杂,并且毫无意义地不那么可读。谢谢你的时间!对不起,s.charAt(I)>=最大的.charAt(0)
检查有什么意义?这个条件已经被temp.compareTo(最大)>0
表达式测试过了,不是吗?这是一个快速(!)检查
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;
}
}
}