当字符串中有重复项时,查找子字符串的中间索引

时间:2017-12-01 17:53:39

标签: java string oop substring

我正在处理Java编码问题并遇到以下问题。

问题: 给定一个字符串,“xyz”是否出现在字符串的中间?要定义中间,我们会说“xyz”左右两侧的字符数必须至少相差一个

xyzMiddle("AAxyzBB") → true
xyzMiddle("AxyzBBB") → false

我的代码

public boolean xyzMiddle(String str) {
  boolean result=false;
  if(str.length()<3)result=false;
  if(str.length()==3 && str.equals("xyz"))result=true;
  for(int j=0;j<str.length()-3;j++){
    if(str.substring(j,j+3).equals("xyz")){
       String rightSide=str.substring(j+3,str.length());
       int rightLength=rightSide.length();
       String leftSide=str.substring(0,j);
       int leftLength=leftSide.length();
       int diff=Math.abs(rightLength-leftLength);
       if(diff>=0 && diff<=1)result=true;
       else result=false;
    }
  }
  return result;
}

我得到的输出: 运行大多数测试用例但是在某些边缘情况下失败,涉及在字符串中出现“xyz”不止一次

示例:

xyzMiddle("xyzxyzAxyzBxyzxyz")

我现在的方法是从索引0开始采用“xyz”。我理解了这个问题。我想要一个条件只使用字符串操作函数的解决方案。

注意:我需要使用子串等字符串操作来解决这个问题。我不考虑使用list,stringbuffer / builder等。会很感激可以在我的代码上构建的答案。

3 个答案:

答案 0 :(得分:1)

根本不需要循环,因为您只想检查xyz是否在中间。

字符串的格式为

prefix + "xyz" + suffix

前缀和后缀的内容无关紧要;唯一重要的是它们的长度差异至多为1。

取决于字符串的长度(假设它至少为3):

  • 如果(字符串的长度 - xyz的长度)是偶数,则前缀和后缀必须具有相同的长度。在这种情况下:

    int prefixLen = (str.length()-3)/2;
    result = str.substring(prefixLen, prefixLen+3).equals("xyz");
    
  • 否则,前缀和后缀的长度差异为1.在这种情况下:

    int minPrefixLen = (str.length()-3)/2;
    int maxPrefixLen = minPrefixLen+1;
    result = str.substring(minPrefixLen, minPrefixLen+3).equals("xyz") || str.substring(maxPrefixLen, maxPrefixLen+3).equals("xyz");
    

事实上,你甚至不需要这里的子串。您可以使用str.regionMatches代替,并避免创建子字符串,例如对于第一种情况:

result = str.regionMatches(prefixLen, "xyz", 0, 3);

答案 1 :(得分:0)

超级简单的解决方案:

  1. 使用Apache StringUtils分割字符串。 具体而言,splitByWholeSeparatorPreserveAllTokens
  2. 想想这个问题。 具体来说,如果令牌位于字符串的中间,那么拆分调用必须返回偶数个令牌(参见上面的步骤1)。 零在这里算作偶数。
  3. 如果令牌数是偶数,请添加第一组(令牌的前半部分)的长度,并将其与第二组的长度进行比较。 注意细节, 空令牌表示令牌本身的出现。 您可以将此计为零长度,计为令牌的长度,或者将其计为任意数字,只要您始终将其视为相同的数字。
  4. if(lengthFirstHalf == lengthSecondHalf)令牌位于中间。

答案 2 :(得分:0)

管理您的代码,我保持案例str.lengt<3str.lengt==3不变。 从@ Andy的答案中汲取灵感,我考虑了这种模式

  

前缀+ 'XYZ' +后缀

并且,在寻找匹配时,如果他们遵守规则 IsMiddle ,我也会控制它,就像你定义它一样。如果找到符合规则的匹配,则循环中断并返回成功,否则循环继续。

public boolean xyzMiddle(String str) {
      boolean result=false;
      if(str.length()<3)
              result=false;
      else if(str.length()==3 && str.equals("xyz"))
              result=true;
      else{
          int preLen=-1;   
          int sufLen=-2;
          int k=0;
          while(k<str.lenght){
              if(str.indexOf('xyz',k)!=-1){
                count++;
                k=str.indexOf('xyz',k);
                //check if match is in the middle
                preLen=str.substring(0,k).lenght;
                sufLen=str.substring(k+3,str.lenght-1).lenght;
                if(preLen==sufLen || preLen==sufLen-1 || preLen==sufLen+1){
                   result=true;
                   k=str.length; //breaks the while loop
                }
                else
                   result=false;
              }
              else
                k++;
          }


        }
      return result;
    }