2

在这些 HackerRank Java 挑战之一中,有一个问题被定义为:

问题

我们定义以下术语:

  • Lexicographical Order,也称为字母或字典顺序,按如下方式对字符进行排序:A < B < ...< Y < Z < a < b ... < y < z

  • 字符串的子串是字符串中连续的字符块。例如,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) 之前都是正确的。我不知道为什么它在那一步变成了错误的,但确实如此。

有人可以帮我吗?

谢谢!

4

3 回答 3

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)同时初始化largestsmallest

于 2018-02-16T12:12:37.623 回答
2

您不能同时将某个子字符串与迄今为止最小的子字符串和迄今为止最大的子字符串进行比较。尤其是条件

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

是有问题的。举个例子

smallest   ad
largest    bx
temp       bc

在此示例中,您的代码将得出结论 bc 小于 ad

于 2018-02-16T12:13:31.893 回答
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。

于 2018-02-16T13:01:35.460 回答