You are given a string S consisting of letters 'a' and 'b'. The task is to rearrange letters in S so that it contains three consecutive letters 'a' and three consecutive letters 'b'. What is the minimum necessary number of swaps of neighbouring letters to achieve this?
Write a function:
class Solution { public int solution(String S); }
that, given a string S of length N, returns the number of swaps after which S would contain "aaa" and "bbb" as substrings. If it's not possible to rearrange the letters in such a way, the function should return −1.
Examples:
1. Given S = "ababab", the function should return 3. The sequence of swaps could be as follows: ababab → abaabb → aababb → aaabbb.
2. Given S = "abbbbaa", the function should return 4. The sequence of four swaps is: abbbbaa → babbbaa → bbabbaa → bbbabaa → bbbbaaa.
3. Given S = "bbbababaaab", the function should return 0. S already contains both "aaa" and "bbb" as substrings.
4. Given S = "abbabb", the function should return −1. It is not possible to obtain the required result from S as there are only two letters 'a'.
Write an efficient algorithm for the following assumptions:
- N is an integer within the range [1..100,000];
- string S is made only of the characters 'a' and/or 'b'.
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
class Solution {
public int solution(String S) {
int[] count = new int[] {0, 0};
int[][] pos = new int[2][S.length()];
int[] poscount = new int[] {0, 0};
boolean[] has3 = new boolean[] {false, false};
for (int i = 0; i < S.length(); i++) {
int n = S.charAt(i) - 'a';
count[n]++;
if (i > 1 && !has3[n])
has3[n] = (S.charAt(i) == S.charAt(i - 1) && S.charAt(i) == S.charAt(i - 2));
pos[n][poscount[n]++] = i;
}
if (count[0] < 3 || count[1] < 3)
return -1;
for (int i = 0; i < 2; i++)
if (has3[i]) {
int ans = S.length();
int i2 = i == 0 ? 1 : 0;
for (int j = 0; j < poscount[i2] - 2; j++)
ans = Math.min(ans, pos[i2][j + 2] - pos[i2][j] - 2);
return ans;
}
Map<String, Integer> d = new HashMap<>();
Queue<String> q = new LinkedList<>();
for (int i = 0; i < S.length(); i++) {
String w = i + 8 < S.length() ? S.substring(i, i + 8) : S.substring(i);
if (!d.containsKey(w)) {
d.put(w, 0);
q.add(w);
}
}
while (!q.isEmpty()) {
String w = q.remove();
if (w.indexOf("aaa") != -1 && w.indexOf("bbb") != -1)
return d.get(w);
for (int i = 0; i < w.length() - 1; i++) {
String w2 = w.substring(0, i) + w.charAt(i + 1) + w.charAt(i) + w.substring(i + 2);
if (!d.containsKey(w2)) {
d.put(w2, d.get(w) + 1);
q.add(w2);
}
}
}
return 0;
}
}
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
class Solution {
public int solution(String S) {
int[] count = new int[] {0, 0};
int[][] pos = new int[2][S.length()];
int[] poscount = new int[] {0, 0};
boolean[] has3 = new boolean[] {false, false};
for (int i = 0; i < S.length(); i++) {
int n = S.charAt(i) - 'a';
count[n]++;
if (i > 1 && !has3[n])
has3[n] = (S.charAt(i) == S.charAt(i - 1) && S.charAt(i) == S.charAt(i - 2));
pos[n][poscount[n]++] = i;
}
if (count[0] < 3 || count[1] < 3)
return -1;
for (int i = 0; i < 2; i++)
if (has3[i]) {
int ans = S.length();
int i2 = i == 0 ? 1 : 0;
for (int j = 0; j < poscount[i2] - 2; j++)
ans = Math.min(ans, pos[i2][j + 2] - pos[i2][j] - 2);
return ans;
}
Map<String, Integer> d = new HashMap<>();
Queue<String> q = new LinkedList<>();
for (int i = 0; i < S.length(); i++) {
String w = i + 8 < S.length() ? S.substring(i, i + 8) : S.substring(i);
if (!d.containsKey(w)) {
d.put(w, 0);
q.add(w);
}
}
while (!q.isEmpty()) {
String w = q.remove();
if (w.indexOf("aaa") != -1 && w.indexOf("bbb") != -1)
return d.get(w);
for (int i = 0; i < w.length() - 1; i++) {
String w2 = w.substring(0, i) + w.charAt(i + 1) + w.charAt(i) + w.substring(i + 2);
if (!d.containsKey(w2)) {
d.put(w2, d.get(w) + 1);
q.add(w2);
}
}
}
return 0;
}
}
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
class Solution {
public int solution(String S) {
int[] count = new int[] {0, 0};
int[][] pos = new int[2][S.length()];
int[] poscount = new int[] {0, 0};
boolean[] has3 = new boolean[] {false, false};
for (int i = 0; i < S.length(); i++) {
int n = S.charAt(i) - 'a';
count[n]++;
if (i > 1 && !has3[n])
has3[n] = (S.charAt(i) == S.charAt(i - 1) && S.charAt(i) == S.charAt(i - 2));
pos[n][poscount[n]++] = i;
}
if (count[0] < 3 || count[1] < 3)
return -1;
for (int i = 0; i < 2; i++)
if (has3[i]) {
int ans = S.length();
int i2 = i == 0 ? 1 : 0;
for (int j = 0; j < poscount[i2] - 2; j++)
ans = Math.min(ans, pos[i2][j + 2] - pos[i2][j] - 2);
return ans;
}
Map<String, Integer> d = new HashMap<>();
Queue<String> q = new LinkedList<>();
for (int i = 0; i < S.length(); i++) {
String w = i + 8 < S.length() ? S.substring(i, i + 8) : S.substring(i);
if (!d.containsKey(w)) {
d.put(w, 0);
q.add(w);
}
}
while (!q.isEmpty()) {
String w = q.remove();
if (w.indexOf("aaa") != -1 && w.indexOf("bbb") != -1)
return d.get(w);
for (int i = 0; i < w.length() - 1; i++) {
String w2 = w.substring(0, i) + w.charAt(i + 1) + w.charAt(i) + w.substring(i + 2);
if (!d.containsKey(w2)) {
d.put(w2, d.get(w) + 1);
q.add(w2);
}
}
}
return 0;
}
}
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
class Solution {
public int solution(String S) {
int[] count = new int[] {0, 0};
int[][] pos = new int[2][S.length()];
int[] poscount = new int[] {0, 0};
boolean[] has3 = new boolean[] {false, false};
for (int i = 0; i < S.length(); i++) {
int n = S.charAt(i) - 'a';
count[n]++;
if (i > 1 && !has3[n])
has3[n] = (S.charAt(i) == S.charAt(i - 1) && S.charAt(i) == S.charAt(i - 2));
pos[n][poscount[n]++] = i;
}
if (count[0] < 3 || count[1] < 3)
return -1;
for (int i = 0; i < 2; i++)
if (has3[i]) {
int ans = S.length();
int i2 = i == 0 ? 1 : 0;
for (int j = 0; j < poscount[i2] - 2; j++)
ans = Math.min(ans, pos[i2][j + 2] - pos[i2][j] - 2);
return ans;
}
Map<String, Integer> d = new HashMap<>();
Queue<String> q = new LinkedList<>();
for (int i = 0; i < S.length(); i++) {
String w = i + 8 < S.length() ? S.substring(i, i + 8) : S.substring(i);
if (!d.containsKey(w)) {
d.put(w, 0);
q.add(w);
}
}
while (!q.isEmpty()) {
String w = q.remove();
if (w.indexOf("aaa") != -1 && w.indexOf("bbb") != -1)
return d.get(w);
for (int i = 0; i < w.length() - 1; i++) {
String w2 = w.substring(0, i) + w.charAt(i + 1) + w.charAt(i) + w.substring(i + 2);
if (!d.containsKey(w2)) {
d.put(w2, d.get(w) + 1);
q.add(w2);
}
}
}
return 0;
}
}
The solution obtained perfect score.