简体   繁体   English

(Java)字母子字符串比较最终导致错误的结果

[英](Java) alphabetic substring comparison ends up with a wrong result

In one of these HackerRank Java challenges, there is a problem which is defined as: 在这些HackerRank Java挑战中,有一个问题定义为:

The problem 问题

We define the following terms: 我们定义以下术语:

  • Lexicographical Order, also known as alphabetic or dictionary order, orders characters as follows: A < B < ...< Y < Z < a < b ... < y < z 词典顺序,也称为字母顺序或字典顺序,按以下顺序对字符进行排序:A <B <... <Y <Z <a <b ... <y <z

  • A substring of a string is a contiguous block of characters in the string. 字符串的子字符串是字符串中连续的字符块。 For example, the substrings of abc are a, b, c, ab, bc, and abc. 例如,abc的子字符串是a,b,c,ab,bc和abc。

Given a string, s , and an integer, k , complete the function so that it finds the lexicographically smallest and largest substrings of length k . 给定一个字符串s和一个整数k ,完成函数,以便找到字典上长度为k的 最小最大子字符串。

Here is my (not fully working) solution: 这是我的(不是完全有效的)解决方案:

My code 我的密码

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));
    }
}

According to the HackerRank, this code fails for 2 out of 6 cases. 根据HackerRank,此代码在6种情况中有2种失败。 One is as follows: 一种如下:

ASDFHDSFHsdlfhsdlfLDFHSDLFHsdlfhsdlhkfsdlfLHDFLSDKFHsdfhsdlkfhsdlfhsLFDLSFHSDLFHsdkfhsdkfhsdkfhsdfhsdfjeaDFHSDLFHDFlajfsdlfhsdlfhDSLFHSDLFHdlfhs
30

The expected output is: 预期的输出是:

ASDFHDSFHsdlfhsdlfLDFHSDLFHsdl
sdlkfhsdlfhsLFDLSFHSDLFHsdkfhs

But mine becomes: 但是我变成了:

DFHSDLFHDFlajfsdlfhsdlfhDSLFHS
sdlkfhsdlfhsLFDLSFHSDLFHsdkfhs

At debug mode, I found that the smallest substring was correct until the 67th iteration (i). 在调试模式下,我发现最小的子字符串在第67次迭代(i)之前是正确的。 I don't know why it changes to a wrong one at that step but it does. 我不知道为什么在那一步它会变成错误的,但是确实如此。

Can anyone help me on that, please? 有人可以帮我吗?

Thanks! 谢谢!

The problem is that you are trying your comparison for both largest and smallest in a single loop. 问题是您要在单个循环中尝试比较最大和最小。 More specifically, this line is problematic: 更具体地说,这行是有问题的:

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
}

You may want to continue the loop on j to detect the smallest substring, but break out of the loop on j to detect the largest substring. 您可能要继续在j上执行循环以检测最小的子字符串,但要中断在j上执行循环以检测最大的子字符串。 That's why the two checks should be done independently of each other. 这就是为什么两次检查应相互独立进行的原因。

A few minor points to consider: 需要考虑的一些小问题:

  • You do not need to write largest = s.substring(i, i + k) , because it is the same as largest = temp ; 您不需要编写largest = s.substring(i, i + k) ,因为它与largest = s.substring(i, i + k) largest = temp相同; same goes for smallest . smallest
  • You do not need the nested loop at all compareTo performs lexicographic comparison for you. 您根本不需要嵌套循环compareTo为您执行字典比较。

Essentially, your program could be reduced to this: 本质上,您的程序可以简化为:

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;
    }
}

Note that the loop can start from i = 1 because you used s.substring(0, k) to initialize both largest and smallest . 注意循环可以开始从i = 1 ,因为你用s.substring(0, k)来初始化largestsmallest

You cannot compare a certain substring to both the smallest so far and the largest so far at the same time. 您不能同时将某个子字符串与到目前为止的最小字符串和迄今为止的最大字符串进行比较。 Especially the condition 特别是条件

temp.charAt(j) == smallest.charAt(j)
                    || temp.charAt(j) == largest.charAt(j)

is problematic. 有问题。 Take for example 举个例子

smallest   ad
largest    bx
temp       bc

In this example your code will conclude that bc is smaller than ad 在此示例中,您的代码将得出结论:bc小于ad

I propose a simple optimisation: a quick peek at the first characters. 我建议进行一个简单的优化:快速浏览一下第一个字符。

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;
        }
    }
}

For the example, comparisons drop from 222 to 14. 例如,比较从222下降到14。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM