At the moment, the entirety of the solution is in your main
method. More often than not, in OOP, your main
method should be reserved to be the entry point of your program only, rather than the entire program. This helps to keep your code better organized, and easier to understand and maintain.
In this particular case, I would move the code that actually solves the problem to another class, to help make it more general, and just read the input and print the output in main
.
There a few naming concerns that stood out. First, the problem states the input numbers are n
and k
, which are often used for mathematical notation as a matter of convention; however, those don't necessarily translate well to code, as code should preferably be written in such a way that it makes the intentions clear.
First, I would change the input variable names like so:
n
to strLength
max
(or, k
in the problem) to maxCharChangesAllowed
s
(the input string of As and Bs) to targetStr
(or something similar)
Moving them to a static method signature in a new class would look like this:
class CodeForce676C {
public static int solve(int strLength, int maxCharChangesAllowed, String targetStr) {
// ...
}
}
Similarly, a
, b
are not very clear, I would suggest countOfA
and countOfB
. We will extract that logic to a separate method as well. We can eliminate your char z
and just return the result directly from the method. We can also simplify the return by using Java's ternary operator instead of if-then-else
structure.
We can also leverage the fact that the length of the string is provided as input, and save ourselves a String.length()
calculation.
Note that declaring int i, j
iteration counters outside of the loop signature is not recommended, unless you are using those variables for something besides the loop itself (which you are not). The compiler will know that i
won't be needed after the loop is exited so it can just remove it then, and if you have another loop in the same method that also uses i
it will just make a new one.
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';
}
Likewise we could also move the other part of the logic (that uses max1
and count
) to its own method. I renamed max1
to changesRemaining
, count
to charCount
, and temp
to substringLength
. The algorithm itself was already addressed in Tunaki's answer, so I simply adapted your existing algorithm to make the code easier to understand and cleaner.
Here is a working demo on repl.it. To run the given test case, run it and type in the console: 8 1 aabaabaa
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;
}
}