我面临以下问题的写逻辑问题。
我有两个字符串数组:
List1:包含500万字符串
List2:将在用户输入上创建并包含一些字符串/字符(例如a,b,c,g,l,pd,sp,mta)
现在我必须根据list2中的startsWith字符串将list1拆分为多个列表,如上例所示。我需要创建8个列表,作为' a '' b '' c ',' g ',' l ',' pd ',' sp '和' mta '
但上面的条件是我必须只迭代List1或List2一次。即算法的最差复杂度应该是List1的大小(500万)。
允许使用collections.sort()方法
我试过的代码
// Create List for search strings.
List<String> CharList = new ArrayList<String>();
CharList.add("a");
CharList.add("b");
CharList.add("e");
CharList.add("z");
CharList.add("4");
CharList.add("1");
CharList.add("zi");
List<String> recordList = new ArrayList<String>();
// Creating dummy data with 100 character in live environment it can be
// around 50 lakhs strings
for (int i = 0; i < 100; i++) {
char[] chars = "abcdefghijklmnopqrstuvwxyzABCGDKL0123456789".toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i1 = 0; i1 < 6; i1++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
String output = sb.toString();
recordList.add(output);
}
// Adding some data mannually
recordList.add("zink");
recordList.add("zebra");
recordList.add("zzzzzz");
Collections.sort(CharList, String.CASE_INSENSITIVE_ORDER);
Collections.sort(recordList, String.CASE_INSENSITIVE_ORDER);
System.out.println("RECORDLIST ===>" + recordList);
System.out.println("***************************************************");
System.out.println("Charlist ===>" + CharList);
System.out.println("***************************************************");
List<List> lists = new ArrayList<List>();
int startIndex = 0, charPointer = 0;
while (startIndex < recordList.size() && charPointer < CharList.size()) {
List<String> temp = new ArrayList<String>();
boolean isHit = false;
String currentRecord = recordList.get(startIndex);
String partitionSattement = CharList.get(charPointer);
while (currentRecord.startsWith(partitionSattement.toUpperCase())
|| currentRecord.startsWith(partitionSattement.toLowerCase())) {
temp.add(recordList.get(startIndex));
isHit = true;
startIndex++;
}
if (!isHit) {
startIndex++;
}
if (!temp.isEmpty()) {
lists.add(temp);
System.out.println(CharList.get(charPointer) + "====>" + temp);
}
charPointer++;
}
答案 0 :(得分:0)
在这种情况下,仅使用String
startsWith
方法无法使用。考虑如果第一个模式与任何输入都不匹配会发生什么 - 您将在输入列表中循环遍历所有字符串而不查找匹配项,即使后续模式匹配确实存在。
我们需要做的是将每个模式与每个输入字符串的初始字符进行比较并相应地处理。我们假设我们有一个输入字符串str
和一个模式pat
。让subStr
成为pat.length()
的第一个str
字符。现在,我们可以使用subStr
pat
方法比较String
和compareToIgnoreCase
。有三种情况需要考虑:
subStr < pat
移动到下一个输入字符串。
subStr == pat
将str
添加到pat
的输出中,然后移至下一个输入字符串。
subStr > pat
转到下一个模式。
这里有一些代码可以说明(我已尽可能保留您的变量名称)。
List<List<String>> output = new ArrayList<>();
for(int i=0; i<CharList.size(); i++) output.add(new ArrayList<String>());
int startIndex=0;
int charPointer=0;
while(startIndex < recordList.size() && charPointer < CharList.size())
{
String charStr = CharList.get(charPointer);
String recStr = recordList.get(startIndex);
int cmp;
if(recStr.length() < charStr.length())
{
cmp = -1;
}
else
{
String recSubStr = recStr.substring(0, charStr.length());
cmp = recSubStr.compareToIgnoreCase(charStr);
}
if(cmp <= 0)
{
if(cmp == 0) output.get(charPointer).add(recStr);
startIndex++;
}
else
{
charPointer++;
}
}
for(int i=0; i<CharList.size(); i++)
{
System.out.println(CharList.get(i) + " : " + output.get(i));
}
此外,您应该注意,当您包含一个本身以另一个模式开始的模式(例如"zi"
和"z"
)时,较长的模式永远不会匹配,因为较短的模式将捕获所有输入
答案 1 :(得分:0)
我可以在您的代码中看到两个问题:
您应该删除以下细分:
if (!isHit) {
startIndex++;
}
实际上你根本不需要那个isHit变量。如果字符串与模式不匹配,那么您仍然需要将其与下一个模式进行比较。
您应该按降序对数组进行排序。正如SirRaffleBuffle在另一个答案中指出的那样,你应该首先将字符串与较长的模式进行比较。按降序对字符串和模式进行排序将自动解决此问题。