移位字符串分组:Java 解法与单元测试
在编程的世界里,字符串操作一直是经典且常见的问题。今天,我们要来探讨 LeetCode 上的第 249 题——移位字符串分组。这道题不仅有趣,还能帮助我们更好地理解字符串的处理和分组逻辑。让我们一起来看看如何用 Java 解决这个问题,并进行单元测试。
题目描述
题目要求我们对字符串进行“移位”操作,具体如下:
- 右移:将字符串中每个字母都变为其在字母表中后续的字母,其中用 'a' 替换 'z'。比如,“abc” 能够右移为 “bcd”,“xyz” 能够右移为 “yza”。
- 左移:将字符串中每个字母都变为其在字母表中之前的字母,其中用 'z' 替换 'a'。比如,“bcd” 能够左移为 “abc”,“yza” 能够左移为 “xyz”。
我们可以不断地向两个方向移动字符串,形成无限的移位序列。例如,移动 “abc” 来形成序列:... <-> "abc" <-> "bcd" <-> ... <-> "xyz" <-> "yza" <-> ... <-> "zab" <-> "abc" <-> ...
给定一个字符串数组 strings,将属于相同移位序列的所有 strings[i] 进行分组。你可以以任意顺序返回答案。
示例
- 示例 1:
- 输入:strings = ["abc","bcd","acef","xyz","az","ba","a","z"]
- 输出:[["acef"],["a","z"],["abc","bcd","xyz"],["az","ba"]]
- 示例 2:
- 输入:strings = ["a"]
- 输出:[["a"]]
解题思路
要解决这个问题,我们可以按照以下步骤进行:
- 初始化结果列表:创建一个 ArrayList,用于存储最终的分组结果。
- 遍历输入字符串数组:使用两个嵌套的循环遍历字符串数组。
- 检查字符串是否为空且长度相等:在内层循环中,检查当前字符串是否为空且长度是否与外层循环的字符串相等。
- 计算移位差值:计算两个字符串的第一个字符之间的移位差值。
- 检查每个字符的移位差值:遍历字符串的每个字符,检查它们之间的移位差值是否一致。
- 将符合条件的字符串添加到分组中:如果所有字符的移位差值一致,则将当前字符串添加到分组中,并将其标记为空字符串以避免重复处理。
- 将当前字符串添加到分组中:在外层循环结束时,将当前字符串添加到分组中,并将其标记为空字符串。
- 返回结果:返回最终的分组结果。
代码实现
package _249;
import java.util.ArrayList;
import java.util.List;
public class LeetCode249 {
public List<List<String>> groupStrings(String[] strings) {
var result = new ArrayList<List<String>>();
for (var i = 0; i < strings.length; i++) {
var item = new ArrayList<String>();
for (var j = 0; j < strings.length; j++) {
if (!strings[j].isEmpty() && i != j && strings[i].length() == strings[j].length()) {
var shift = strings[i].charAt(0) - strings[j].charAt(0);
var ok = true;
for (var k = 0; k < strings[i].length(); k++) {
var temp = strings[i].charAt(k) - strings[j].charAt(k);
if (temp != shift && Math.abs(temp) + Math.abs(shift) != 26) {
ok = false;
break;
}
}
if (ok) {
item.add(strings[j]);
strings[j] = "";
}
}
}
if (!strings[i].isEmpty()) {
item.add(strings[i]);
result.add(item);
}
strings[i] = "";
}
return result;
}
}
单元测试
为了确保我们的解决方案是正确的,我们可以编写单元测试来验证其功能。以下是一个简单的单元测试示例:
package _249;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class LeetCode249Test {
@Test
void testGroupStrings() {
LeetCode249 solution = new LeetCode249();
String[] input = {"az", "ba"};
List<List<String>> expected = List.of(
List.of("az", "ba")
);
assertEquals(expected, solution.groupStrings(input));
}
}
总结
通过上述步骤和代码实现,我们可以轻松地将属于相同移位序列的字符串进行分组。这个问题不仅考察了我们对字符串操作的理解,还帮助我们更好地掌握分组逻辑和单元测试的编写。
希望这篇文章能帮助你更好地理解和解决这个问题。如果你有任何疑问或建议,欢迎在评论区留言。让我们一起在编程的道路上不断进步!