英文:
Replace all doubled or tripled letters with single ones
问题
public static String doubleLetters(String str) {
StringBuilder ret = new StringBuilder(str.length());
if (str.length() == 0) return "";
for (int i = 0; i < str.length(); i++) {
if (i < str.length() - 2 && str.charAt(i) == str.charAt(i + 1) && str.charAt(i) == str.charAt(i + 2)) {
ret.append(str.charAt(i));
i += 2; // Skip the next two identical characters
} else if (i < str.length() - 1 && str.charAt(i) == str.charAt(i + 1)) {
ret.append(str.charAt(i));
i++; // Skip the next identical character
} else {
ret.append(str.charAt(i));
}
}
return ret.toString();
}
英文:
Task:
> For a given string of characters consisting only of letters: a, b and
> c swap all doubled or tripled letters for single ones
I prepared such a code:
public static String doubleLetters(String str) {
StringBuilder ret = new StringBuilder(str.length());
if (str.length() == 0) return "";
for (int i = 1; i < str.length(); i++)
{
if(str.charAt(i) == str.charAt(i-1)
|| str.charAt(i) == str.charAt(i-1) && str.charAt(i) == str.charAt(i-2))
{
ret.append(str.charAt(i));
}
}
return ret.toString();
}
However, I cannot define the condition to take into account tripled letters.
> By entering "aaabbbccc" I want "abc".
> By entering "aabbcc" I want "abc".
> By entering "aaaaabbbbbbbccc" I want "aabbbc".
IMPORTANT
Letters that are converted to 1 letter are not taken into account.
Please help me how to approach this problem.
答案1
得分: 2
以下是代码的翻译部分:
public static String eliminateMultipleLetters(String s) {
StringBuilder sb = new StringBuilder(); // 用于循环的更好方式是StringBuilder,而不是字符串连接
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) != s.charAt(i + 1))
sb.append(s.charAt(i));
}
sb.append(s.charAt(s.length() - 1)); // 添加最后一个字符
return sb.toString();
}
Edit: 要替换3个字符为1个字符,只要有3个字符,然后如果可能的话就是2个字符,你可以按照以下方式操作(逻辑非常相似,只是最后一步变得更加复杂):
public static String replace3or2Letters(String s) {
if (s.length() < 2)
return s;
StringBuilder sb = new StringBuilder();
int i;
for (i = 0; i < s.length() - 2; i++) {
sb.append(s.charAt(i));
if (s.charAt(i) == s.charAt(i + 1)) {
if (s.charAt(i) == s.charAt(i + 2))
i += 2;
else
i++;
}
}
if (i == s.length() - 2) {
sb.append(s.charAt(s.length() - 2));
if (s.charAt(s.length() - 2) != s.charAt(s.length() - 2))
sb.append(s.charAt(s.length() - 1));
} else if (i == s.length() - 1) {
sb.append(s.charAt(s.length() - 1));
}
return sb.toString();
}
更加优雅的方式:
public static String replaceUpToXbySingle(String s, int x) { // x = 3 for you
StringBuilder sb = new StringBuilder();
char last = 'c'; // 无论如何
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (count == 0 || s.charAt(i) != last) {
if (count > 0)
sb.append(last);
last = s.charAt(i);
count = 1;
} else if (++count == x) {
sb.append(last);
count = 0;
}
}
if (count > 0)
sb.append(last);
return sb.toString();
}
英文:
It is not entirely clear whether you want to replace only triple or double letters or a repeated character of any length by a single one. I'm assuming the latter one:
public static String eliminateMultipleLetters(String s) {
StringBuilder sb = new StringBuilder(); // better for loops than concatenation
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) != s.charAt(i + 1))
sb.append(s.charAt(i));
}
sb.append(s.charAt(s.length() - 1)); // append last character
return sb.toString();
}
Edit: to replace 3 characters by 1 as long as there are 3 and then 2 if possible, you could do as follows (the logic is very similar, just the step at the end gets more complicated):
public static String replace3or2Letters(String s) {
if (s.length() < 2)
return s;
StringBuilder sb = new StringBuilder();
int i;
for (i = 0; i < s.length() - 2; i++) {
sb.append(s.charAt(i));
if (s.charAt(i) == s.charAt(i + 1)) {
if (s.charAt(i) == s.charAt(i + 2))
i += 2;
else
i++;
}
}
if (i == s.length() - 2) {
sb.append(s.charAt(s.length() - 2));
if (s.charAt(s.length() - 2) != s.charAt(s.length() - 2))
sb.append(s.charAt(s.length() - 1));
} else if (i == s.length() - 1) {
sb.append(s.charAt(s.length() - 1));
}
return sb.toString();
}
More elegant:
public static String replaceUpToXbySingle(String s, int x) { // x = 3 for you
StringBuilder sb = new StringBuilder();
char last = 'c'; // whatever
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (count == 0 || s.charAt(i) != last) {
if (count > 0)
sb.append(last);
last = s.charAt(i);
count = 1;
} else if (++count == x) {
sb.append(last);
count = 0;
}
}
if (count > 0)
sb.append(last);
return sb.toString();
}
答案2
得分: 1
以下是更新后的回复中的翻译部分:
如果您想替换三个一组,然后两个一组的组合,您需要构建一个连续频率的列表。在拥有这个列表之后,您可以通过对总数应用div/mod逻辑来构建一个字符串。
我包括了一个扩展`Map.Entry`的`Pair`类,它存储键值关联。
```java
import java.util.*;
public class StringUtil {
public static void main(String[] args) {
System.out.println(dedupe("aabbcc").equals("abc"));
System.out.println(dedupe("aaabbbccc").equals("abc"));
System.out.println(dedupe("aaaaabbbbbbbccc").equals("aabbbc"));
}
public static String dedupe(String str) {
if (str == null || str.isEmpty()) {
return str;
}
StringBuilder buffer = new StringBuilder();
List<Pair<Character, Integer>> pairs = new ArrayList<>();
char[] chars = str.toCharArray();
char curr, prev = chars[0];
int total = 0, i, add3, add2;
for (i = 1; i < chars.length; i++) {
curr = chars[i];
total++;
if (curr != prev) {
pairs.add(new Pair<>(prev, total));
total = 0;
prev = curr;
}
}
total++;
pairs.add(new Pair<>(prev, total));
for (Pair<Character, Integer> pair : pairs) {
total = pair.getValue();
add3 = total / 3;
for (i = 0; i < add3; i++) {
buffer.append(pair.getKey());
}
total %= 3;
add2 = total / 2;
for (i = 0; i < add2; i++) {
buffer.append(pair.getKey());
}
total %= 2;
for (i = 0; i < total; i++) {
buffer.append(pair.getKey());
}
}
return buffer.toString();
}
private static final class Pair<K, V> implements Map.Entry<K, V> {
private final K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V old = this.value;
this.value = value;
return old;
}
}
}
英文:
Updated response
If you want to replace groups of three, followed by groups of two, you need to build a list of contiguous frequencies. After you have this list, you could build a string by applying div/mod logic to the total.
I included a Pair
class that extends Map.Entry
which stores key-value associations.
import java.util.*;
public class StringUtil {
public static void main(String[] args) {
System.out.println(dedupe("aabbcc").equals("abc"));
System.out.println(dedupe("aaabbbccc").equals("abc"));
System.out.println(dedupe("aaaaabbbbbbbccc").equals("aabbbc"));
}
public static String dedupe(String str) {
if (str == null || str.isEmpty()) {
return str;
}
StringBuilder buffer = new StringBuilder();
List<Pair<Character, Integer>> pairs = new ArrayList<>();
char[] chars = str.toCharArray();
char curr, prev = chars[0];
int total = 0, i, add3, add2;
for (i = 1; i < chars.length; i++) {
curr = chars[i];
total++;
if (curr != prev) {
pairs.add(new Pair<>(prev, total));
total = 0;
prev = curr;
}
}
total++;
pairs.add(new Pair<>(prev, total));
for (Pair<Character, Integer> pair : pairs) {
total = pair.getValue();
add3 = total / 3;
for (i = 0; i < add3; i++) {
buffer.append(pair.getKey());
}
total %= 3;
add2 = total / 2;
for (i = 0; i < add2; i++) {
buffer.append(pair.getKey());
}
total %= 2;
for (i = 0; i < total; i++) {
buffer.append(pair.getKey());
}
}
return buffer.toString();
}
private static final class Pair<K, V> implements Map.Entry<K, V> {
private final K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V old = this.value;
this.value = value;
return old;
}
}
}
Original response
All you would need to do it store a previous (prev
) value and then just loop over the characters and append to buffer if current (curr
) does not match the previous.
public class StringUtil {
public static void main(String[] args) {
System.out.println(dedupe("aaabbbccc")); // "abc"
}
public static String dedupe(String str) {
StringBuilder buffer = new StringBuilder();
char prev = 0;
for (char curr : str.toCharArray()) {
if (curr != prev) {
buffer.append(curr);
prev = curr;
}
}
return buffer.toString();
}
}
答案3
得分: 1
另一种方法:计算字符连续出现的次数,然后通过将它们的数量除以三来批量打印。
public static String doubleLetters(String str) {
StringBuilder ret = new StringBuilder(str.length());
if (str.length() == 0) return "";
int count = 1;
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i) == str.charAt(i-1)) {
count++;
continue;
}
for (; count > 0; count -= 3)
ret.append(str.charAt(i-1));
count = 1;
}
for (; count > 0; count -= 3)
ret.append(str.charAt(str.length() - 1));
return ret.toString();
}
英文:
Another approach: count the number of consecutive occurrences of a character, and then print them in bulk, by dividing their number by three.
public static String doubleLetters(String str) {
StringBuilder ret = new StringBuilder(str.length());
if (str.length() == 0) return "";
int count = 1;
for (int i = 1; i < str.length(); i++)
{
if (str.charAt(i) == str.charAt(i-1)) {
count++;
continue;
}
for (; count > 0; count -= 3)
ret.append(str.charAt(i-1));
count = 1;
}
for (; count > 0; count -= 3)
ret.append(str.charAt(str.length() - 1));
return ret.toString();
}
答案4
得分: 0
然而,我无法定义考虑重复字母的条件。
通过输入"aaabbbccc",我想得到"abc"。
通过输入"aabbcc",我想得到"abc"。
通过输入"aaaaabbbbbbbccc",我想得到"aabbbc"。
重要提示:转换为1个字母的字母不被考虑在内。
想象一下这个问题分为三个阶段:
- 首先,生成输入中所有单个、双重或三重字母出现的序列(或流)。
- 接下来,将序列中的每个出现替换为其第一个字母。
- 最后,将序列(或流)重新组合成一个单一的字符串实例。
为了使这个解决方案更易读,我会使用一个主方法和一个静态的帮助方法,如下所示:
public static String deDupe(String input) {
String result = generateStreamOfOccurrences(input)
.map(occurrence -> occurrence.substring(0, 1))
.collect(Collectors.joining());
return result;
}
private static Stream<String> generateStreamOfOccurrences(String str) {
String input = str;
List<String> listOfOccs = new ArrayList<>();
if (input != null) {
while (input.length() > 0) {
String occ = input.substring(0, 1);
if (input.length() > 2 && input.substring(1, 3).equals(occ + occ)) {
occ = input.substring(0, 3);
}
else if (input.length() > 1 && input.substring(1, 2).equals(occ)) {
occ = input.substring(0, 2);
}
input = input.substring(occ.length());
listOfOccs.add(occ);
}
}
return listOfOccs.stream();
}
主函数很容易阅读。它获取了一个包含字符串中的字母出现次数的流,每个出现次数都是其第一个字母的单个、双重或三重。获取这个 Stream<String>
管道的工作封装在辅助函数 generateListOfOccurrences()
中。然后,流中的每个元素都被替换为只包含第一个字母的元素。然后它们被连接在一起形成结果。
英文:
> However, I cannot define the condition to take into account tripled
> letters.
>
> By entering "aaabbbccc" I want "abc".
>
> By entering "aabbcc" I want "abc".
>
> By entering "aaaaabbbbbbbccc" I want "aabbbc".
>
> IMPORTANT Letters that are converted to 1 letter are not taken into
> account.
Imagine this problem in three stages:
- First, generate a sequence (or a stream) of all the single, double, or triple letter occurrences in your input
- Next, replace each of the occurrences in the sequence with its first letter
- Finally, put the sequence (or stream) back together into a single String instance
To realize this solution very readably, I would use a main method and a static helper method as follows:
public static String deDupe(String input) {
String result = generateStreamOfOccurrences(input)
.map(occurrence -> occurrence.substring(0, 1)
.collect(Collectors.joining());
return result;
}
private static Stream<String> generateStreamOfOccurrences(String str) {
String input = str;
List<String> listOfOccs = new ArrayList<>();
if (input != null) {
while (input.length() > 0) {
String occ = input.substring(0, 1);
if (input.length() > 2 && input.substring(1, 3).equals(occ + occ)) {
occ = input.substring(0, 3);
}
else if (input.length() > 1 && input.substring(1, 2).equals(occ)) {
occ = input.substring(0, 2);
}
input = input.substring(occ.length());
listOfOccs.add(occ);
}
}
return listOfOccs.stream();
}
The main function is easy to read. It obtains a stream of letter occurrences in the String, each of which is a single, double, or triple of its first letter. The work of obtaining this Stream<String>
pipeline is encapsulated in the helper function generateListOfOccurrences()
. Then each of the elements in the stream are replaced by elements that consist of just the 1st letter. Then they are joined together to form the result.
答案5
得分: 0
然而,我无法定义考虑三重字母的条件。
通过输入"aaabbbccc",我想要得到"abc"。
通过输入"aabbcc",我想要得到"abc"。
通过输入"aaaaabbbbbbbccc",我想要得到"aabbbc"。
重要的是,转换为一个字母的字母不会被考虑在内。
想象一下这个问题分为三个阶段:
- 首先,生成输入中所有单个、双重或三重字母出现的序列(或流)。
- 接下来,用序列中每个出现的第一个字母替换它。
- 最后,将序列(或流)重新组合成一个字符串实例。
要以非常可读的方式实现这个解决方案,我会使用一个主方法和一个静态的辅助方法,如下所示:
public static String deDupe(String input) {
String result = generateStreamOfOccurrences(input)
.map(occurrence -> occurrence.substring(0, 1))
.collect(Collectors.joining());
return result;
}
private static Stream<String> generateStreamOfOccurrences(String input) {
List<String> listOfOccs = new ArrayList<>();
if (input != null) {
while (input.length() > 0) {
String occ = input.substring(0, 1);
if (input.length() > 2 && input.substring(1, 3).equals(occ + occ))
occ = input.substring(0, 3);
if (input.length() > 1 && input.substring(1, 2).equals(occ))
occ = input.substring(0, 2);
input = input.substring(occ.length());
listOfOccs.add(occ);
}
}
return listOfOccs.stream();
}
主函数易于阅读。它获得一个字符串中的字母出现的流,每个出现都是其第一个字母的单个、双重或三重。获得这个Stream<String>
管道的工作被封装在辅助函数generateListOfOccurrences()
中。
英文:
> However, I cannot define the condition to take into account tripled
> letters.
>
> By entering "aaabbbccc" I want "abc".
>
> By entering "aabbcc" I want "abc".
>
> By entering "aaaaabbbbbbbccc" I want "aabbbc".
>
> IMPORTANT Letters that are converted to 1 letter are not taken into
> account.
Imagine this problem in three stages:
- First, generate a sequence (or a stream) of all the single, double, or triple letter occurrences in your input
- Next, replace each of the occurrences in the sequence with its first letter
- Finally, put the sequence (or stream) back together into a single String instance
To realize this solution very readably, I would use a main method and a static helper method as follows:
public static String deDupe(String input) {
String result = generateStreamOfOccurrences(input)
.map(occurrence -> occurrence.substr(0, 1)
.collect(Collectors.joining());
return result;
}
private static Stream<String> generateStreamOfOccurrences(String input) {
List<String> listOfOccs = new ArrayList<>();
if (input != null) {
while (input.length() > 0) {
String occ = input.substring(0, 1);
if (input.length() > 2 && input.substring(1, 3).equals(occ + occ))
occ = input.substring(0, 3);
if (input.length() > 1 && input.substring(1, 2).equals(occ))
occ = input.substring(0, 2);
input = input.substring(occ.length());
listOfOccs.add(occ);
}
}
return listOfOccs.stream();
}
The main function is easy to read. It obtains a stream of letter occurrences in the String, each of which is a single, double, or triple of its first letter. The work of obtaining this Stream<String>
pipeline is encapsulated in the helper function generateListOfOccurrences()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论