首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >寻找具有相同字符的连续字符串的最大长度

寻找具有相同字符的连续字符串的最大长度
EN

Code Review用户
提问于 2016-09-08 11:50:54
回答 2查看 9.8K关注 0票数 6

我正在解这个问题来自代码强制。,我有一个复杂度为O(n平方)的解。但是,在某些测试用例上,时间限制超过了。问题是:

高中生Vasya得到了一串长n的生日礼物。这个字符串仅由字母'a‘和'b’组成。Vasya表示字符串的美,它是由等号组成的子字符串(连续子序列)的最大长度。Vasya只能更改原始字符串的k个字符。他所能达到的最大美是什么?输入输入的第一行包含两个整数n和k (1 ≤ n ≤ 100 000, 0 ≤ k ≤ n) --字符串的长度和要更改的最大字符数。第二行包含字符串,只包含字母'a‘和'b’。输出打印唯一的整数--字符串Vasya的最大美可以通过更改不超过k个字符来实现。示例输入/输出示例:8 1 aabaabaa输出5

我的解决办法是:

代码语言:javascript
复制
import java.util.Scanner;
public class CF676C {
public static void main(String args[]){
    Scanner in = new Scanner(System.in);
    int n = in.nextInt(), max = in.nextInt(),a=0,b=0;

    String s = in.next();
    int i,j;
    for(i=0;i<n;i++){
        if(s.charAt(i) == 'a'){
            ++a;
        }
        else{
            ++b;
        }
    }
    char z;
    if(a<=b){
        z='a';
    }
    else{
        z='b';
    }
    int max1;
    int count=0;
    int temp=0;
    for(i=0;i<s.length();i++)
    {
        max1=max;
        count=0;
        for(j=i;j<s.length()&&max1!=-1;j++)
        {
            if(s.charAt(j)==z&&max1!=-1)
            {
                max1--;
            }
            if(max1!=-1)
            {
                count++;
            }
        }
        if(count>temp)
        {
            temp=count;
        }
    }
    System.out.println(temp);
}
}

我不明白如何减少代码占用的时间。有没有其他可用的解决方案或方法?

EN

回答 2

Code Review用户

回答已采纳

发布于 2016-09-08 13:56:44

是的,您可以更快地解决这个问题,使用一个O(n)算法,使用一个左指针和一个右指针来分隔子字符串。

对于输入字符串中的每个字符,其思想是保持数组在给定的'a'指针之间计数left'b'的数量,这将表示子字符串的开始和当前字符。

当每个'a'或每个'b'的计数小于允许更改的字符数时,我们可以考虑进行更改并递增答案。然后,当这两个计数都大于允许更改的字符数时,这意味着我们不能更改更多的字符,因此我们达到了最大长度:left指针增加了,该指针处的字符计数减少了。

'a''b'字符的计数可以建模为整数数组(索引0对应于'a'的计数,而索引1对应于'b'的计数)。

代码语言:javascript
复制
Scanner in = new Scanner(System.in);
int n = in.nextInt(), max = in.nextInt();
String s = in.next();

int left = 0, answer = 0;
int[] count = { 0, 0 };
for (char c : s.toCharArray()) {
    count[c - 'a']++;
    if (Math.min(count[0], count[1]) > max) {
        count[s.charAt(left) - 'a']--;
        left++;
    } else {
        answer++;
    }
}
System.out.println(answer);

这种方法通过了所有挑战的测试。

票数 7
EN

Code Review用户

发布于 2016-09-09 01:24:12

目前,整个解决方案都在您的main方法中。在OOP中,您的main方法通常应该保留为仅作为程序的入口点,而不是整个程序的入口点。这有助于使代码更好地组织起来,更容易理解和维护。

在这种情况下,我会将实际解决问题的代码移到另一个类中,以帮助使其更通用,只需读取输入并在main中打印输出即可。

有几个突出的命名问题。首先,问题说明输入数字是nk,它们通常用于数学表示法,作为惯例;然而,这些数字不一定能很好地转换成代码,因为代码最好是以这样一种方式来编写,这样才能清楚地表明意图。

首先,我将更改输入变量名如下:

  • nstrLength
  • max (或,问题中的k )到maxCharChangesAllowed
  • s ( As和Bs的输入字符串)到targetStr (或类似的东西)

将它们移动到新类中的静态方法签名如下所示:

代码语言:javascript
复制
class CodeForce676C {
    public static int solve(int strLength, int maxCharChangesAllowed, String targetStr) {
        // ...
    }
}

同样的,ab也不是很清楚,我建议countOfAcountOfB。我们也将把这个逻辑提取到一个单独的方法中。我们可以消除您的char z,直接从方法返回结果。我们还可以通过使用三元算子而不是if-then-else结构来简化返回。

我们还可以利用字符串长度作为输入的事实,并为自己节省String.length()计算。

请注意,不建议在循环签名之外声明int i, j迭代计数器,除非您将这些变量用于除循环本身之外的其他内容(而不是)。编译器将知道在循环退出后不需要i,因此它可以删除它,如果在同样使用i的方法中有另一个循环,那么它只会创建一个新的循环。

代码语言:javascript
复制
private static char findCharWithLeastFrequency(String targetStr, int strLength) {
    int countOfA = 0;
    int countOfB = 0;
    for (int i = 0; i < strLength; i++) {
        targetStr.charAt(i) == 'a' ? ++countOfA : ++countOfB;
        if (targetStr.charAt(i) == 'a') {
            ++countOfA;
        } else {
            ++countOfB;
        }
    }
    return countOfA <= countOfB ? 'a' : 'b';
}

同样,我们也可以将逻辑的另一部分(使用max1count)移动到自己的方法中。我把max1改名为changesRemainingcount改名为charCounttemp改名为substringLength。算法本身已经在图纳基的回答中得到了解决,所以我只是简单地修改了现有的算法,以使代码更容易理解和更简洁。

这是一个在repl.it上的工作演示。要运行给定的测试用例,请运行它并输入控制台:8 1 aabaabaa

代码语言:javascript
复制
import java.util.Scanner;

class Main {
    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        // Read the values from the input
        int n = in.nextInt();
        int k = in.nextInt(); 
        String s = in.next();
        // Solve the calculation and print the result to console:
        System.out.println(CodeForce676C.solve(n, k, s));
    }
}

class CodeForce676C {

    public static int solve(int strLength, int maxCharChangesAllowed, String targetStr) {
        char leastFrequentChar = findCharWithLeastFrequency(targetStr, strLength);
        return getLengthOfLongestPossibleSubstring(
                targetStr, 
                maxCharChangesAllowed, 
                leastFrequentChar, 
                strLength);
    }

    private static char findCharWithLeastFrequency(String targetStr, int strLength) {
        int countOfA = 0;
        int countOfB = 0;
        for (int i = 0; i < strLength; i++) {
            if (targetStr.charAt(i) == 'a') {
                ++countOfA;
            } else {
                ++countOfB;
            }
        }
        return countOfA <= countOfB ? 'a' : 'b';
    }

    private static int getLengthOfLongestPossibleSubstring(
            String targetStr, 
            int maxCharChangesAllowed, 
            char leastFrequentChar,
            int strLength) {
        int changesRemaining;
        int charCount = 0;
        int substringLength = 0;
        for (int i = 0; i < strLength; i++) {
            // Reset values on each outer iteration
            changesRemaining = maxCharChangesAllowed;
            charCount = 0;
            for (int j = i; j < strLength && changesRemaining != -1; j++) {
                if (targetStr.charAt(j) == leastFrequentChar && changesRemaining != -1) {
                    changesRemaining--;
                }
                if (changesRemaining != -1) {
                    charCount++;
                }
            }
            if(charCount > substringLength) {
                substringLength = charCount;
            }
        }
        return substringLength;
    }
}
票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/140840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档