重新排列单词以在一行中容纳最多单词并使用 Java 创建更少的行数

Posted

技术标签:

【中文标题】重新排列单词以在一行中容纳最多单词并使用 Java 创建更少的行数【英文标题】:Re-shuffle the words to accommodate max words in a single line and create less number of lines using Java 【发布时间】:2019-10-08 18:16:19 【问题描述】:

重新排列单词以在 42 个字符的单行中容纳最多单词,并使用 Java 创建更少的行数

我必须创建逗号分隔的单词,并且一行的最大大小为 42。 字符串可以以这样的方式重新洗牌,以适应最大字数而不会超过 42 行大小和更少的行数。 为此,我根据单词的长度对单词进行了排序。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ManageWords 
private static final int LINE_MAX_SIZE = 45;

public static void main(String[] args) 
List<String> wordList = new ArrayList<String>();
wordList.add("URUNDI");
wordList.add("AFGHANISTAN");
wordList.add("WEST GERMANY");
wordList.add("ALAND ISLANDS");
wordList.add("VIET-NAM - DEMOCRATIC REPUBLIC OF");

Collections.sort(wordList, Comparator.comparingInt(String::length));
List<String> concatenatedWordsLines = new ArrayList<String>();

for (int i = 0; i < wordList.size(); i++) 
String concatenatedWords = wordList.get(i);
int j = i + 1;

if (concatenatedWords.length() < LINE_MAX_SIZE) 
while (concatenatedWords.length() < LINE_MAX_SIZE && j <= wordList.size() - 1) 
if (concatenatedWords.concat("," + wordList.get(j)).length() < LINE_MAX_SIZE) 
concatenatedWords = concatenatedWords.concat("," + wordList.get(j));
 else 
break;

j++;


concatenatedWordsLines.add(concatenatedWords);
i = j - 1;



for (String s : concatenatedWordsLines) 
System.out.println(s + " : " + s.length());



使用上面的代码,我得到以下 3 行的结果,

 
    URUNDI,AFGHANISTAN,WEST GERMANY
    ALAND ISLANDS
    VIET-NAM - DEMOCRATIC REPUBLIC OF
    

而我期望它在 2 行中,其大小小于或等于 42,如下所示,

 
    URUNDI,VIET-NAM - DEMOCRATIC REPUBLIC OF
    AFGHANISTAN,WEST GERMANY,ALAND ISLANDS
    

目的是用尽可能少的行容纳所有单词。

【问题讨论】:

【参考方案1】:

您的问题是bin-packing problem 的变体。这是一个 NP 难题,因此除非您的输入非常小,否则试图找到最佳解决方案可能并不可行。

有几种方法可以解决:

您可以选择first-fit greedy algorithm(易于实施,在许多情况下可以提供不错的结果)。这是问题的 2 近似值,因此在最坏的情况下,您的行数将是最佳解决方案的两倍。

您还可以实现蛮力算法(使用枚举算法测试所有可能的组合,只适合非常小的输入但找到最佳解决方案)。

使用 java 的另一种可能性是使用Ilog 之类的接口将其插入Cplex solver(或任何其他ILP 求解器)。

恕我直言,ILP 方法应该受到青睐,因为它是学习使用的有用工具,一旦你完成了接口部分,程序编写起来会非常简单,而且它已经过优化,会给你返回一个小型实例的最佳答案,以及不可处理的实例的良好可行解决方案。

【讨论】:

以上是关于重新排列单词以在一行中容纳最多单词并使用 Java 创建更少的行数的主要内容,如果未能解决你的问题,请参考以下文章

华为OD机试 2023最新 字符串重新排列字符串重新排序(C++ 100%)

华为机试真题 C++ 实现字符串重新排列2022.11 Q4新题

华为机试真题 C++ 实现字符串重新排列2022.11 Q4新题

华为机试真题 Java 实现字符串重新排列2022.11 Q4新题

整齐打印

Lc5413_重新排列句子中的单词