搜索String数组以获取子字符串并返回多个值的最有效方法?

时间:2014-03-01 19:47:54

标签: java arrays substring

假设您获得了包含以下内容的数组:

约旦

JORD

安娜

罗布

RobJord

你想要返回一个包含Jord的所有值的数组(即Jord,Jordan,RobJord),这是最强高效的方法。

我正在使用Java,但我不允许使用java.util数组函数。

3 个答案:

答案 0 :(得分:2)

我想到了这种方法:

public ArrayList<String> search(String searchString, String[] names)
{
  ArrayList<String> searchList = new ArrayList<String>();

  for (String name : names)
  {
    if(name.contains(searchString))
    {
      searchList.add(name);
    }
  }

  return searchList;
}

现在要搜索,请使用:

String[] names = {"Jordan", "Jord", "Anna", "Rob", "RobJord"};
String searchString = "Jord";

ArrayList<String> filterList = search(searchString, names);

它不使用java.util.Arrays方法,并且还以干净的方式完成工作,更不用说,它的速度很快。

现在如果你甚至不能使用ArrayList,那么你有两个选择:
1.自己实施ArrayList并使用它。
2.请遵循以下方法:

public String[] search(String searchString, String[] names)
{
  int size = getSize(searchString, names);
  String[] searchList = new String[size];

  int index = 0;
  for (String name : names)
  {
    if(name.contains(searchString))
    {
      searchList[index++] = name;
    }
  }

  return searchList;
}

// Returns appropriate size for the Search List
private int getSize(String searchString, String[] names)
{
  int size = 0;
  for (String name : names)
  {
    if(name.contains(searchString))
    {
      size++;
    }
  }

  return size;
}

答案 1 :(得分:1)

好吧,因为这听起来像家庭作业,它是解决,但我会考虑这个非常英国的伪代码。它避免使用java.util.*(例如ArrayList或Arrays类)并且只使用原始构造。

count = 0
for each item in the input
    if the rule matches
       increase count by 1

create output array of size count

target index = 0
for each item in the input
    if the rule matches
        add the item to the output array at the target index,
        and increase the target index by 1

return the output array

此代码在complexity中为O(n),即使它循环输入(n)两次,因为这是一个常数因素,而O(2*n)2*O(n) }是O(n)

现在,常量边界可以稍微减少,而不是只计算第一遍,也压缩第一遍的值,然后只复制压缩值(小于或等于n)到一个新的较小数组。它仍然是O(n),但可能的挂钟时间略低......或者它可能会执行更糟,具体取决于细微的缓存/ JIT /数据因素。哦,现代计算机的复杂功能!

改善O(n)“效率”界限并没有什么微不足道的方法 - 特别是对于一次运行没有。

答案 2 :(得分:0)

需要一些代码来设置所有内容并且它将是可怕的样式,但是你可以将你的字符串转换为字符串数组,并且有一个 int 数组,表示“Jord”中字母的ascii值,这样您就可以获得通过原语而不是对象引用进行检查的好处。将您正在检查的字符传递给条件块,该块使用

的int值对其进行求值

'J', 'o', 'r', 'd' //74, 111, 114, 100

同样,我只是建议这种疯狂,因为你非常注重效率。马上我会说,将所有东西转移到字符上都需要时间效率。在大型处理任务中可以获得最大的好处,例如在整个1000页的电子书中检查Jord,因为初始化只发生一次(或者在大块中,我想也许有大量数据,但无论哪种方式都有益)

//assuming its case sensitive: ascii values for 'J' 'o' 'r' 'd'
int[] charArr = new int[]{74, 111, 114, 100};

同样,它需要一些设置来阻碍性能,加上它只是奇怪,但它确实给你带来了原始int验证的好处。

另一个想法是考虑某些字母的统计数字后跟另一个字母。例如,“J”跟随任何元音的可能性非常高,因此“J”后跟“o”但仍然不是“Jord”因此非常高,因为我们只有5个元音(加y,奇怪的一个...)你可能会得到“Jork”,你浪费了检查“o”和“r”。所以说到这一点,也许最好将扫描仪向上移动几个字母(或你当前的数组索引计数器 - 无论你迭代哪种方式),在你为“J”建立匹配后检查“d” ”。我认为这会提高效率。

基本上我是说如果你以一种迭代方式逐字逐句地检查它,那么第一步是匹配“J”,然后第二步是跳过< / em>“o”并检查“r”或“d”。或者换句话说,找一个候选人,并积极地消除候选人

编辑:我实际上是说在步骤2中检查“d”并且如果步骤2检出,则不考虑检查“r”直到步骤3,因为这样你的代码会更简单 - 从头开始​​,移动到最后,然后向后迭代到开始+ 1。如果在步骤2中检查“r”,那么步骤3和4将是锯齿形索引以遍历