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

createh52个月前 (02-01)技术教程15



在编程的世界里,字符串操作一直是经典且常见的问题。今天,我们要来探讨 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字符串(java字符串截取方法有哪些)

String简介String类在java.lang包下,所以使用的时候不需要导包String类代表字符串,java中所有字符串文字例如"abc",都被实现为此类的实例,也就是说,java程序中所有双引...

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

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

漫画:为什么Java里面的String对象是不可变的?

String的不变性String在Java中特别常用,相信很多人都看过他的源码,在JDK中,关于String的类声明是这样的:public final class Str...

「Java必修课」判断String是否包含子串的四种方法及性能对比

1 简介判断一个字符串是否包含某个特定子串是常见的场景,比如判断一篇文章是否包含敏感词汇、判断日志是否有ERROR信息等。本文将介绍四种方法并进行性能测试。2 四种方法2.1 JDK原生方法Strin...

Java中字符串StringBuffer和StringBuilder的使用

Java中表示字符串的有三个类:String、StringBuffer和StringBuilder。其中,String的长度是不可变的,而StringBuffer和StringBuilder是长度可变...

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

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