移位字符串分组:Java 解法与单元测试

createh54个月前 (02-01)技术教程22



在编程的世界里,字符串操作一直是经典且常见的问题。今天,我们要来探讨 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"]]

解题思路

要解决这个问题,我们可以按照以下步骤进行:

  1. 初始化结果列表:创建一个 ArrayList,用于存储最终的分组结果。
  2. 遍历输入字符串数组:使用两个嵌套的循环遍历字符串数组。
  3. 检查字符串是否为空且长度相等:在内层循环中,检查当前字符串是否为空且长度是否与外层循环的字符串相等。
  4. 计算移位差值:计算两个字符串的第一个字符之间的移位差值。
  5. 检查每个字符的移位差值:遍历字符串的每个字符,检查它们之间的移位差值是否一致。
  6. 将符合条件的字符串添加到分组中:如果所有字符的移位差值一致,则将当前字符串添加到分组中,并将其标记为空字符串以避免重复处理。
  7. 将当前字符串添加到分组中:在外层循环结束时,将当前字符串添加到分组中,并将其标记为空字符串。
  8. 返回结果:返回最终的分组结果。

代码实现

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));
    }
}

总结

通过上述步骤和代码实现,我们可以轻松地将属于相同移位序列的字符串进行分组。这个问题不仅考察了我们对字符串操作的理解,还帮助我们更好地掌握分组逻辑和单元测试的编写。

希望这篇文章能帮助你更好地理解和解决这个问题。如果你有任何疑问或建议,欢迎在评论区留言。让我们一起在编程的道路上不断进步!



相关文章

Java中常用的字符串替换的4种方法

在 Java 中,字符串替换是常见的操作。以下是 4 种常用的字符串替换方法,每种方法都有其适用场景和特点。方法 1:String.replace()功能:替换字符串中所有匹配的子字符串。特点:区分大...

Java语言中字符串的存储(java字符串的使用)

字符串是程序中使用频率最高的一种数据类型,Java为了加强程序的运行速度,因此设计了两种不同的方法来生成字符串对象。一种是调用String类的构造函数,另一种是使用“”。这两种方法产生的字符串对象在内...

为什么Java中的String是不可变的(Immutable)

在Java中,String类型是用于表示字符串的类,而字符串则是字符序列,是Java编程中最常用的数据类型之一。String类是不可变的,这意味着一旦创建,字符串的值就不能改变,下面我们就来介绍一下为...

你只会用 SB?试试 StringJoiner,真香

你只会用 StringBuilder/ StringBuffer 拼接字符串?那你就 OUT 了!!如果需要拼接分隔符的字符串,建议使用 Java 8 中的这款拼接神器:StringJoiner,你值...