查找字符串中最长的相同字符序列

时间:2015-08-05 18:42:06

标签: java

此代码应该输出字符串中的字符连续运行自身的最长运行时间。虽然问题是输出: 8 (应该 5 )。我只想问一下这段代码的问题。

public class Sample {
    public static void main(String[] args) {
        String setofletters = "aaakkcccccczz"; /* 15 */
        int output = runLongestIndex(setofletters);
        System.out.println("Longest run that first appeared in index:" + output);
    }

    public static int runLongestIndex(String setofletters) {
        int ctr = 0;
        int ctrstor = 0;
        int ii = 0;
        int output = 0;

        // loops until the last character in the string
        for (int i = 0; i < setofletters.length() - 1; i++) {
            // checks if the letter is the same to the next
            if (setofletters.charAt(i) == setofletters.charAt(i++)) {
                ctr++;
                ii = i++;
                // loops until the letter in the index is no longer equal
                while (setofletters.charAt(i) == setofletters.charAt(ii)) {
                    ii++;
                    ctr++;
                }

                if (ctr > ctrstor) {
                    output = i;
                }
                // storing purposes
                ctrstor = ctr;
            }
            // resets the counter
            ctr = 0;
        }
        return output;
    }
}

12 个答案:

答案 0 :(得分:2)

更新抱歉,我误解了您的问题,您需要在代码中进行以下更改才能使其正常工作。(带注释的行)

   public static int runLongestIndex(String setofletters){
    int ctr = 1; // every character is repeated at least once, so you should initialize it to 1, not 0
    int ctrstor = 0;
    int ii = 0;
    int output = 0;

    for (int i = 0; i < setofletters.length() - 1; i++) {
        if (i < setofletters.length() - 1 && setofletters.charAt(i) == setofletters.charAt(i+1)) { // i++ is not same as i+1
            ctr++;
            ii = i+1; // i++ is not same as i+1
            while (setofletters.charAt(i) == setofletters.charAt(ii)) {
                ii++;
                ctr++;
            }

            if (ctr > ctrstor) {
                output = i;
            }
            ctrstor = ctr;
        }
        ctr = 1; // for the same reason I mentioned above
    }
    return output;
}

编辑:编写代码的最简单方法是:

public static int runLongestIndex(String setofletters){ 
   int ctr = 1;
    int output = 0;
    int j=0;
    for(int i=0; i<setofletters.length()-1;i++){
        j=i;
        while(i <setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
            i++;
            ctr++;
        }
        if(ctr>output){
            output=j;
        }
        ctr = 1;
    }
    return output;
}

为什么要为输出分配i?您应该将ctr分配给output

更改

   if(ctr>ctrstor){
      output=i;
   }

 if(ctr>ctrstor){
      output=ctr;
 }

而且我认为你应该改变

 if(setofletters.charAt(i)==setofletters.charAt(i++))

 if(i<setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){

您应该将ctr初始化为1但不要0,因为每个字符至少重复一次。

答案 1 :(得分:1)

我会为你解决这个问题的Scala实现。

这是自动测试(采用ScalaTest的BDD风格)

import org.scalatest._
class RichStringSpec extends FlatSpec with MustMatchers {
  "A rich string" should "find the longest run of consecutive characters" in {
    import Example._
    "abceedd".longestRun mustBe Set("ee", "dd")
    "aeebceeedd".longestRun mustBe Set("eee")
    "aaaaaaa".longestRun mustBe Set("aaaaaaa")
    "abcdefgh".longestRun mustBe empty
  }
}

以下是命令式样式实现,具有嵌套循环和可变变量,正如您通常在Java或C ++中选择的那样:

object Example {
  implicit class RichString(string: String) {
    def longestRun: Set[String] = {
      val chunks = mutable.Set.empty[String]
      val ilen = string.length
      var gmax = 0
      for ((ch, curr) <- string.zipWithIndex) {
        val chunk = mutable.ListBuffer(ch)
        var next = curr + 1
        while (next < ilen && string(next) == ch) {
          chunk += string(next)
          next = next + 1
        }
        gmax = chunk.length max gmax
        if (gmax > 1) chunks += chunk.mkString
      }
      chunks.toSet.filter( _.length == gmax )
    }
  }
}

以下是一个函数式实现,因此没有变量,没有循环但是带有结果累加器的尾递归和模式匹配将每个字符与下一个字符进行比较(疯狂!不是吗?):

object Example {
  implicit class RichString(string: String) {
    def longestRun: Set[String] = {
      def recurse(chars: String, chunk: mutable.ListBuffer[Char], chunks: mutable.Set[String]): Set[String] = {
        chars.toList match {
          case List(x, y, _*) if (x == y) =>
            recurse(
              chars.tail, 
              if (chunk.isEmpty) chunk ++= List(x, y) else chunk += y, 
              chunks
            )
          case Nil =>
            // terminate recursion
            chunks.toSet
          case _ => // x != y
            recurse(
              chars.tail,
              chunk = mutable.ListBuffer(), 
              chunks += chunk.mkString
            )
        }
      }
      val chunks = recurse(string, mutable.ListBuffer(), mutable.Set.empty[String])
      val max = chunks.map(_.length).max
      if (max > 0) chunks.filter( _.length == max ) else Set()
    }
  }
}

例如,对于给定的"aeebceeedd"字符串,上述两种实现都将构建以下一组块(重复字符)

Set("ee", "eee", "dd")

并且他们将过滤那些具有最大长度的块(结果为"eee")。

答案 2 :(得分:1)

此代码适用于任何长度的字符串序列。

public class LongestStringSequqnce {

static String myString = "aaaabbbbcccchhhhiiiiibbbbbbbbbccccccc";
static int largestSequence = 0;
static char longestChar = '\0';

public static void main(String args[]) {
    int currentSequence = 1;
    char current = '\0';
    char next = '\0';

    for (int i = 0; i < myString.length() - 1; i++) {
        current = myString.charAt(i);
        next = myString.charAt(i + 1);

        // If character's are in sequence , increase the counter
        if (current == next) {
            currentSequence += 1;
        } else {
            if (currentSequence > largestSequence) { // When sequence is
                                                     // completed, check if
                                                     // it is longest
                largestSequence = currentSequence;
                longestChar = current;
            }
            currentSequence = 1; // re-initialize counter
        }
    }
    if (currentSequence > largestSequence) { // Check if last string
                                             // sequence is longest
        largestSequence = currentSequence;
        longestChar = current;
    }

    System.out.println("Longest character sequence is of character "
            + longestChar + " and is " + largestSequence + " long");
}

}

来源:http://www.5balloons.info/program-java-code-to-find-longest-character-sequence-in-a-random-string/

答案 3 :(得分:0)

       if(ctr>ctrstor){
            output=i;
        }
        //storing purposes
        ctrstor=ctr;

这看起来像是问题所在。因此,如果您找到8个连续字符,它会将输出设置为8,然后继续。下次通过时,它会找到3个连续的字符,因此不会设置输出,而是设置ctrstor。下次通过它会找到4个连续的字符,这会将输出设置为4

答案 4 :(得分:0)

您的逻辑感觉代码中的陷阱很少:

  1. 代码错误地假设总是有下一个字符来比较当前字符 这对于"a"之类的字符串或任何字符串中的最后一个字符都会失败。

  2. 代码不存储最大字符数,只存储最大索引(i) 需要MaxCount来比较下一个字符序列大小。

  3. 循环for和循环while重复相同的字符子集。

  4. 同样,变量名称样式使得理解代码变得更加困难。

  5. 纠正上述

    public static int runLongestIndex(String setofletters) {
      int maxCount = 0;
      int maxIndex = 0;
    
      // loops each character in the string
      for (int i = 0; i < setofletters.length() - 1; ) {
        // new char sequence starts here
        char currChar = setofletters.charAt(i);
        int count = 1;
        int index = i;
        while ( (index < setofletters.length() - 1) &&
                (currChar == setofletters.charAt(++index)) ) {
           count++;
        } 
    
        if (count > maxCount) {
           maxIndex = i;
           maxCount = count;
        }
        i = index;
      }
      return maxIndex;
    }
    

    请参阅Java DEMO

答案 5 :(得分:0)

我认为你不需要内部循环:

public static int runLongestIndex(String setofletters) {
    if (setofletters == null || setofletters.isEmpty()) {
      return -1;
    }
    int cnt = 1;
    char prevC = setofletters.charAt(0);
    int maxCnt = 1;
    //char maxC = prevC;
    int maxRunIdx = 0;
    int curRunIdx = 0;
    for (int i = 1; i < setofletters.length(); i++){
      final char c = setofletters.charAt(i);
      if (prevC == c) {
        cnt++;
      } else {
        if (cnt > maxCnt) {
          maxCnt = cnt;
          //maxC = prevC;          
          maxRunIdx = curRunIdx;
        }
        cnt = 1;
        curRunIdx = i;
      }
      prevC = c;
    }
    if (setofletters.charAt(setofletters.length() - 1) == prevC) {
      if (cnt > maxCnt) {
        //maxC = prevC;
        maxCnt = cnt;
        maxRunIdx = curRunIdx;
      }
    }
    return maxRunIdx;
  }

和这段代码: 的System.out.println(runLongestIndex( “aaakkcccccczz”)); 给你 5

答案 6 :(得分:0)

这就是我的“同事”如何理解编写可读代码以解决这个问题,即使这样做有效:)

$(document).ready(function() {
  $('.sev_check').each(function() {
    $(this).addClass('unselected');
  });
  $('.sev_check').on('click', function() {
    $(this).toggleClass('unselected');
    $(this).toggleClass('selected');
    $('.sev_check').not(this).prop('checked', false);
    $('.sev_check').not(this).removeClass('selected');
    $('.sev_check').not(this).addClass('unselected');
  });
});

答案 7 :(得分:0)

int indexOfLongestRun(String str){

       char[] ar = str.toCharArray();
       int longestRun = 0;
       int lastLongestRun = 0;
       int index = 0;
       for(int i = ar.length-1; i>0; i--){
           if(ar[i] == ar[i-1]){
               longestRun++;
           }else{
               if(longestRun > lastLongestRun){
                   lastLongestRun = longestRun;
                   longestRun = 0;
                   index = i;
               }
           }
       }

       return index;

答案 8 :(得分:0)

嗯,解决方案有点取决于额外的要求。这是在给定字符串中返回重复字符的FIRST最长序列的代码,这意味着如果你有一个具有相同长度的第二个序列,你永远不会得到它:(。但是,这仍然是一个简单明了的解决方案,好消息 - 它有效!:)

string = 'abbbccddddddddeehhhfffzzzzzzzzdddvyy'

longest_sequence = ''
for i in range(len(string)):
    is_sequence = True
    ch_sequence = ''
    while is_sequence:
        ch_sequence += string[i]
        if i+1 < len(string) and string[i]==string[i+1]:
            i += 1
        else:
            is_sequence = False
    if len(ch_sequence) > len(longest_sequence):
        longest_sequence = ch_sequence
print (longest_sequence)

答案 9 :(得分:0)

@Paolo Angioletti已经使用Scala提供了答案,但是它比需要的要复杂。这个想法与Run-length encoding并没有太大不同。时间复杂度O(n)

def longestConsecutive(s: String): (Char, Int) = {
  Iterator.iterate(('\u0000', 0, 0)) { case (ch, longestRun, i) =>
    val run = (i until s.length)
      .takeWhile(s(_) == s(i))
      .size

    if (run > longestRun) (s(i), run, i + run)
    else (ch, longestRun, i + run)
  }
    .dropWhile(i => s.isDefinedAt(i._3))
    .take(1)
    .map(x => (x._1, x._2))
    .next()
}

经过测试:

("s", "ch", "n")
----------------
("", '\u0000', 0),
("a", 'a', 1),
("aabcddbbbea", 'b', 3),
("abcddbbb", 'b', 3),
("cbccca", 'c', 3)

答案 10 :(得分:0)

#include <iostream>
#include<algorithm> 
using namespace std;

int main() {
    string s="abbcccccbbffffffffff";
    //cin>>s;
    int count=1;
    int maxcount=1;
    int start=0;
    int ps=0;
    
    for (int i=0;i<s.size()-1;i++)
    
    {
        if(s.at(i)==s.at(i+1))
        {
            count +=1;
            maxcount=max(maxcount,count);
        }
        else
        {  
             ps=max(ps,start+count);
            count =1;
            start=i;
        }
    }
   
   for(int i=1;i<=maxcount;i++)
   {
       cout<<s.at(i+ps); 
   }
    
    
    // your code goes here
    return 0;
}

答案 11 :(得分:0)

这是我想到的最简单的方法,它将在一行字符串中打印最长的序列相同字符。

public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        scanner.close();
        
        int count = 0;
        int curCount = 1;
        
        
        for (int i = 0; i < s.length() -1; i++) {
            
            if (s.charAt(i) == s.charAt(i + 1)) {
                curCount++;
                if (curCount > count) {
                    count = curCount;
                }
            }else {
                if (curCount > count) {
                    count = curCount;
                }
                curCount = 1;
            }
        }
                
        System.out.println(count);
    }