【问题标题】:String Manupulation without any array list or tree?没有任何数组列表或树的字符串操作?
【发布时间】:2019-09-23 15:19:16
【问题描述】:

我有一些输入作为字符串。我需要做一些以下事情:

  1. 字数应按长度递增的顺序打印;
  2. 重复多次的单词将被忽略。
  3. 字号大小相同后要打印的字号。

例如:Input : the Black lion was bigger than the red lion;

Output : the was 3 than black 4 ... so on....till the end!

我已尝试使用 Array List 并对它们进行排序。但结果并不像问题那样准确。 任何人都可以帮助实现没有列表、树或正则表达式的结果。

import java.util.*;
class Sorted implements Comparator<String> {

    public int compare(String o1, String o2) {
        if (o1.length() < o2.length()) {
            return -1;
        } else if (o1.length() > o2.length()) {
            return 1;
        } else {
            return 0;
        }
    }
}public class smallToLarge {
    public static void main(String[] args) {
        List<String> arrList = new ArrayList<String>();
        Scanner o = new Scanner(System.in);
        System.out.println("Enter the Sentence : ");
        String sentance = o.nextLine().toLowerCase();
        String[] str = sentance.split("\\s+");
        Arrays.sort(str, new Sorted());
        for (int i = 0; i < str.length; i++) {
            if (!arrList.contains(str[i])) {
                arrList.add(str[i]);
            }
        }
        for (int j = 0; j < arrList.size(); j++) {
            System.out.print(arrList.get(j) + " " + arrList.get(j).length() + " ");
        }
    }
}

【问题讨论】:

  • 你试过使用递归吗?
  • 不知道如何实现!因为它需要排序并且需要删除重复项。 @Goion 你能帮帮我吗?
  • 如果您不想使用数组列表或其他东西,为什么不尝试使用正则表达式之类的东西?
  • @ChathurangaKalana 仅对标准字符串 API 提出了挑战。以及如何使用正则表达式实现?
  • 您可以先删除重复项和担心排序

标签: java string substring


【解决方案1】:

一个人很笨,必须多走路。这里我使用一种数据结构:一个 StringBuilder 来 收集相同长度的单词,因为这样可以轻松检查重复的单词。

int lastSize = 0;
for (;;) {
    int nextSize = determineNextSize(lastSize, input);
    if (nextSize <= lastSize) {
        break;
    }
    StringBuilder words = new StringBuilder();
    collectUniqueWordsOfLength(input, nextSize, words);
    lastSize = nextSize;
    System.out.print(words + lastSize + " ");
}
System.out.println();

输入字符串遍历方式:

int determineNextSize(String input, int size) {
    int minSize = -1;
    int p0 = 0;
    while (p0 < innput.length()) {
        int p = input.indexOf(' ', p0);
        if (p == -1) {
            p = input.length();
        }
        int wordSize = p - p0;
        if (wordSize  > size && (minSize == -1 || wordSize  < minSize)) {
            minSize = wordSize ;
        }
        p0 = p + 1;
    }
    return minSize;
}

void collectUniqueWordsOfLength(String input, int size, StringBuilder words) {
    int p0 = 0;
    while (p0 < innput.length()) {
        int p = input.indexOf(' ', p0);
        if (p == -1) {
            p = input.length();
        }
        int wordSize = p - p0;
        if (wordSize  == size)) {
            String word = input.substring(p0, p) + " ";
            if (!words.toString().contains(word)) {
                words.append(word);
            }
        }
        p0 = p + 1;
    }
}

【讨论】:

  • 感谢您的时间和帮助。我是java编程的初学者。我试过你的代码得到一些错误! if (!words.contains(word)) { words.append(word); } 方法 contains(String) 对于 StringBuilder 类型未定义你能帮我什么是 for(;;)?
  • 改成words.toString().contains(word)
  • 仍然出现错误String index out of range: -12 at java.lang.String.substring(Unknown Source) at abstractExp.A.collectUniqueWordsOfLength(Strplace.java:38) at abstractExp.Strplace.main(Strplace.java:63)@Joop Eggen
  • 更正为input.substring(p0, p),因为子字符串采用起始位置和独占结束位置。
  • 获取输出为3 4 5 6 期望输出类似于the was 3 than black 4 ...等等`@ Joop Eggen
【解决方案2】:

如果您可以使用流,您可以这样做:

String input = "the Black lion was bigger than the red lion";
Pattern.compile("\\s+")
       .splitAsStream(input)
       .collect(Collectors.groupingBy(String::length,TreeMap::new,Collectors.toSet()))
       .forEach((k,v)->{ System.out.print(v + " " + k + " ");});

//to get the output
//[the, red, was] 3 [than, lion] 4 [Black] 5 [bigger] 6

解释:

  • 在每个空格处拆分您的输入
  • 按长度分组收集它们
  • 到 TreeMap 中以升序排序
  • 设置为删除重复项

如果您不希望括号中的字符串将最后一行更改为:

.forEach((k,v)->{ System.out.print(String.join(" ", v) + " " + k + " ");});

【讨论】:

    【解决方案3】:
    String str =  "the Black lion was bigger than the red lion";
    
    str = Arrays.stream( str.split("\\s+")).distinct().collect(Collectors.joining(" ") );
    
        for (int i = 0 ; i <= str.length() ; i++) {
            Matcher m = Pattern.compile("\\b\\w{"+i+"}\\b").matcher(str);
            while(m.find()){
                System.out.print(m.group(0) +" ");
            }
        }
    

    这是使用正则表达式,您将不得不修改一些更改,例如打印字长。 希望这会对你有所帮助。

    【讨论】:

      【解决方案4】:

      这是一个使用 Streams/Collectors 的简单概念证明:

      public static void main(String[] args)
      {
        List<String> arrList = new ArrayList<String>();
        String sentence = "the Black lion was bigger than the red lion";
        var words = sentence.split("\\s");
        // take all the words
        var sortedByLength = Arrays.stream(words)
          // group by string length
          .collect(Collectors.groupingBy(String::length, 
            // sort by string length
            TreeMap::new, 
            // unique words
            Collectors.toSet()));
        // for every length-List(word) pair
        for(var entry : sortedByLength.entrySet())
        {
          // for every word in List(word)
          for(var word : entry.getValue())
          {
            System.out.print(word+" ");
          }
          System.out.print(entry.getKey()+" ");
        }
      }
      

      输出:

      the red was 3 than lion 4 Black 5 bigger 6
      

      您必须根据需要扩展它以读取输入。

      这是一个类似的概念证明,不使用 Lists、Tree(set/map)s 或 Regex:

      public static void main(String[] args)
      {
        String sentence = "the Black lion was bigger than the red lion";
        var words = sentence.split("\\s");
        if(words.length == 0)
          return;
        int nulls = 0;
        for(int i = 0; i < words.length; i++)
        {
          for(int j = i+1; j < words.length; j++)
          {
            if(words[i].equals(words[j]))
            {
              words[i] = null;
              nulls++;
              break;
            }
          }
        }
        var noDupes = new String[words.length - nulls];
        int index = 0;
        for(int i = 0; i < words.length; i++)
        {
          if(words[i] != null)
            noDupes[index++] = words[i];
        }
        Arrays.sort(noDupes, Comparator.comparingInt(String::length));
        for(int i = 0; i < noDupes.length; i++)
        {
          System.out.print(noDupes[i]+" ");
          if(i == noDupes.length - 1)
          {
            System.out.println(noDupes[i].length());
          }
          else if(noDupes[i+1].length() > noDupes[i].length())
          {
            System.out.print(noDupes[i].length()+" ");
          }
        }
      }
      

      输出:

      was the red 3 than lion 4 Black 5 bigger 6
      

      与第一个解决方案相比,它的效率可能非常低,但它确实有效。

      【讨论】:

      • 感谢您的解决方案。但是寻找没有列表或树的破解。仅使用标准字符串 API
      • 感谢您的帮助!
      【解决方案5】:

      我将根据我对您的要求的理解尝试回答,我将首先列出:

      1. 单词应该按长度排序,也可能按词法排序(所以“the”之前的“red”等)
      2. 应忽略出现两次以上(“重复多次”)的词
      3. 应该打印单词,并且只要长度发生变化,就应该打印前一组的长度

      要实现这一点,您可以执行以下操作:

      1. 将文本拆分为单个单词,创建一个数组或列表(您可能希望根据空格和标点符号进行拆分)
      2. 迭代一次以将每个单词“转换”为小写形式(必要时可以内联)
      3. 使用比较器对单词数组/列表进行排序,该比较器首先比较长度,如果长度相等,则按词法比较字符串
      4. 再次遍历单词并将它们收集到 LinkedHashMap 中,其中单词是键,值是该单词的计数器
      5. 遍历该映射的条目集,跳过计数器大于 2(或 1,具体取决于如何解释要求 2)的任何单词
      6. 跟踪前一个单词的长度,当它与当前单词的长度不同时,打印任一长度(取决于您是否需要在单词本身之前或之后打印长度)

      【讨论】:

        猜你喜欢
        • 2015-01-19
        • 2011-08-20
        • 2016-08-18
        • 2015-11-18
        • 1970-01-01
        • 1970-01-01
        • 2013-09-04
        • 2019-03-25
        • 2021-03-13
        相关资源
        最近更新 更多