【问题标题】:Print all the substrings of a given string in order by size按大小顺序打印给定字符串的所有子字符串
【发布时间】:2020-08-05 00:20:47
【问题描述】:

This code I'm using is from this previously asked question. 这个问题已被多次询问和回答,但我特别要求按大小从大到小列出订单。

public static void main(String[] args)
{
    String inputedWord = "ABIGWORD";

    for (String str : breakStringIntoPieces(inputedWord, 2))
    {
        System.out.print("\n") + str;
    }
}

                                                            //Pass in word and minimum
                                                            //substring length to print
public static List<String> breakStringIntoAllPossibleSubstrings(String str, int num)
{                                                               
    List<String> listOfSubstrings = new ArrayList<>();
    Boolean insideLoop = false;

    for(int i=0; i<=str.length()-num; i++)
    {
        for(int j=str.length(); j>=i+num; j--)
        {
            //System.out.println(str.substring(i, j));
            if (insideLoop) //This is simply to not add the complete string to the 
            {               //list. Only substrings

                listOfSubstrings.add(str.substring(i, j));
            }
            insideLoop = true;
        }
    }
    return listOfSubstrings;
}

输出:

ABIGWOR
ABIGWO
ABIGW
ABIG
ABI
AB

BIGWORD
BIGWOR
BIGWO
BIGW
BIG
BI

IGWORD
IGWOR
IGWO
IGW
IG

GWORD
GWOR
GWO
GW

WORD
WOR
WO

ORD
OR

RD

期望的输出:(除了大小没有特殊顺序。这只是一个打字示例。

ABIGWOR
BIGWORD
ABIGWO
BIGWOR
IGWORD
GWORD
ABIGW
IGWOR
BIGWO
IGWO
ABIG
BIGW
WORD
GWOR
GWO
ORD
ABI
BIG
IGW
WOR
AB
BI
IG
GW
WO
OR
RD

从技术上讲,我可以遍历返回的列表并找到所有最大的子字符串,但这会增加太多步骤。我想知道在给定的方法中是否有办法做到这一点。我认为这个过程涉及在每个循环之后操纵 i 和 j 迭代器?

【问题讨论】:

  • 一种方法是使用带有自定义比较器的TreeSet 来订购字符串
  • @William 让我知道答案是否有帮助。另外,请使用原始数据类型boolean insideLoop 以提高效率。
  • @AdithyaUpadhya 谢谢。这真的很有帮助。你能解释一下 item1 和 item 2 是什么吗? “对于大小为 N 的字符串,生成所有子字符串的顺序为 O(N^2)。”这在技术上太慢了吧? ——
  • @WilliamToscano 对于任何排序操作,列表中的元素都必须通过某种逻辑进行比较。因此,在排序操作中,您可以使用Comparator 指定列表中任意两项的比较逻辑。请参考comparator lambda expression上的教程。如果此答案有帮助,请不要忘记投票并将其标记为已接受。这是向其他人表示感谢的一种方式。
  • @WilliamToscano “太慢”是相对的。 O(N^2) 是多项式时间。为了生成字符串的所有子集,而不是子字符串,操作是指数O(2^N)。没有更好的 串行处理 算法来生成子字符串。不过,您可以通过并行处理来提高执行速度。

标签: java loops for-loop substring nested-loops


【解决方案1】:

以最小的更改实现此目的的一种简单方法是按长度对listOfSubstrings ArrayList 进行排序,然后返回结果。这只是使用Collections.sort 进行的一行更改。

public static List<String> breakStringIntoAllPossibleSubstrings(String str, int num) {                                                               
    List<String> listOfSubstrings = new ArrayList<>();

    /* Your code added here... */

    // This will sort in descending order of length
    Collections.sort(listOfSubstrings, (item1, item2) -> item2.length() - item1.length());

    return listOfSubstrings;
}

就时间复杂度而言,对于大小为N的String,生成所有子字符串的顺序为O(N^2)。

额外的排序操作会引入O(N^2 x log(N^2)) = O(N^2 x log(N))。

因此,整体复杂度将是O(N^2 x log(N))

【讨论】:

  • 虽然在这种特殊情况下不需要,但最好使用Integer.compare(item2.length(), item1.length()),这样你就不会忘记在重要的时候这样做。
  • 在Java 8+中,也可以使用listOfSubstrings.sort(Comparator.comparingInt(String::length).reversed())
  • 啊,comparingInt。我一直忘记这件事。我仍然对 Python 中函数式编程的简单性感到敬畏。在 Java 中,这些都是我经常忘记的行话。
  • @AdithyaUpadhya 那么我应该改用 Andreas 代码吗?你们俩都发布了一些很棒的代码,但如果使用 compareInt 更好,请告诉我。
  • 我个人的偏好是Integer.compare(item2.length(), item1.length())。但是,(item1, item2) -&gt; item2.length() - item1.length() 会很详细。如果您刚刚开始学习比较器和函数式编程,那么后者将是一个好的开始。推荐前者,因为它很简单。
猜你喜欢
  • 2020-08-03
  • 2020-03-29
  • 2020-07-20
  • 2020-12-17
  • 2018-08-22
  • 2017-03-30
  • 2015-08-24
  • 2021-02-02
  • 1970-01-01
相关资源
最近更新 更多