如何在 Java 中检查字符串是否为回文串

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个实验中,你将学习如何在 Java 中检查一个字符串是否为回文串。我们将探讨不同的方法,首先是反转字符串并将其与原始字符串进行比较的基本方法。

在此基础上,你将学习使用双指针法的更高效技术。最后,我们将改进回文检查,使其忽略大小写和非字母字符,从而使检查更加可靠。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/StringManipulationGroup(["String Manipulation"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java/BasicSyntaxGroup -.-> java/operators("Operators") java/BasicSyntaxGroup -.-> java/for_loop("For Loop") java/BasicSyntaxGroup -.-> java/while_loop("While Loop") java/StringManipulationGroup -.-> java/strings("Strings") java/SystemandDataProcessingGroup -.-> java/string_methods("String Methods") subgraph Lab Skills java/operators -.-> lab-559990{{"如何在 Java 中检查字符串是否为回文串"}} java/for_loop -.-> lab-559990{{"如何在 Java 中检查字符串是否为回文串"}} java/while_loop -.-> lab-559990{{"如何在 Java 中检查字符串是否为回文串"}} java/strings -.-> lab-559990{{"如何在 Java 中检查字符串是否为回文串"}} java/string_methods -.-> lab-559990{{"如何在 Java 中检查字符串是否为回文串"}} end

反转字符串并比较

在这一步中,我们将首先创建一个简单的 Java 程序来反转字符串,然后将其与原始字符串进行比较。这是理解 Java 中字符串操作的基础步骤,也将作为检查字符串是否为回文串的基石。

首先,让我们创建一个新的 Java 文件。在 WebIDE 左侧的文件资源管理器中,右键点击 ~/project 目录,选择“新建文件”,并将其命名为 StringReverse.java

现在,在编辑器中打开 StringReverse.java 文件,并添加以下代码:

public class StringReverse {

    public static void main(String[] args) {
        String originalString = "hello";
        String reversedString = "";

        // Loop through the original string from end to beginning
        for (int i = originalString.length() - 1; i >= 0; i--) {
            // Append each character to the reversedString
            reversedString += originalString.charAt(i);
        }

        System.out.println("Original string: " + originalString);
        System.out.println("Reversed string: " + reversedString);

        // Compare the original and reversed strings
        if (originalString.equals(reversedString)) {
            System.out.println("The string is the same forwards and backwards.");
        } else {
            System.out.println("The string is NOT the same forwards and backwards.");
        }
    }
}

让我们来分析一下这段代码:

  • String originalString = "hello";:我们声明了一个名为 originalStringString 变量,并将其赋值为 "hello"。
  • String reversedString = "";:我们声明了一个名为 reversedString 的空 String 变量。我们将在这里构建反转后的字符串。
  • for (int i = originalString.length() - 1; i >= 0; i--):这是一个 for 循环,从 originalString 的最后一个字符(索引为 length() - 1)开始,一直到第一个字符(索引为 0)。
  • reversedString += originalString.charAt(i);:在循环内部,originalString.charAt(i) 获取当前索引 i 处的字符。然后,我们将这个字符追加到 reversedString 中。
  • System.out.println(...):这些行将原始字符串和反转后的字符串打印到控制台。
  • if (originalString.equals(reversedString)):这个 if 语句使用 equals() 方法比较 originalStringreversedString。在 Java 中,你应该使用 equals() 方法来比较字符串的内容,而不是 == 运算符。
  • ifelse 代码块根据字符串是否相同打印不同的消息。

保存 StringReverse.java 文件(Ctrl+S 或 Cmd+S)。

现在,打开 WebIDE 底部的终端。确保你位于 ~/project 目录中。如果不是,请输入 cd ~/project 并按回车键。

使用 javac 命令编译 Java 代码:

javac StringReverse.java

如果没有错误,~/project 目录中将创建一个 StringReverse.class 文件。

最后,使用 java 命令运行编译后的 Java 程序:

java StringReverse

你应该会看到类似以下的输出:

Original string: hello
Reversed string: olleh
The string is NOT the same forwards and backwards.

在这种情况下,"hello" 正序和倒序不同,因此程序正确地识别出了这一点。

使用双指针法检查回文串

在上一步中,我们反转了整个字符串来检查它是否为回文串。虽然这种方法可行,但它需要创建一个新的字符串,对于非常长的字符串来说效率较低。更高效的方法是使用 双指针技术

双指针技术涉及使用两个指针(保存索引位置的变量),它们从字符串的两端开始向中间移动。我们比较这两个指针所指向的字符。如果在指针向内移动的过程中,这些字符始终相同,那么该字符串就是回文串。如果发现任何不匹配的情况,那么它就不是回文串。

让我们创建一个新的 Java 程序来实现这一点。在左侧的文件资源管理器中,在 ~/project 目录下创建一个名为 PalindromeChecker.java 的新文件。

打开 PalindromeChecker.java 并添加以下代码:

public class PalindromeChecker {

    public static void main(String[] args) {
        String testString = "madam"; // Let's test with a palindrome
        boolean isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "racecar"; // Another palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "hello"; // Not a palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }
    }

    // Method to check if a string is a palindrome using two pointers
    public static boolean checkPalindrome(String str) {
        // Initialize two pointers
        int left = 0; // Pointer starting from the beginning
        int right = str.length() - 1; // Pointer starting from the end

        // Loop while the left pointer is less than the right pointer
        while (left < right) {
            // Compare characters at the left and right pointers
            if (str.charAt(left) != str.charAt(right)) {
                // If characters don't match, it's not a palindrome
                return false;
            }
            // Move the pointers inwards
            left++;
            right--;
        }

        // If the loop completes without finding any mismatch, it's a palindrome
        return true;
    }
}

以下是新代码的工作原理:

  • 我们创建了一个名为 checkPalindrome 的独立方法,它接受一个 String 作为输入,并返回一个 boolean 值(如果是回文串则返回 true,否则返回 false)。这使我们的代码更有条理且可复用。
  • checkPalindrome 方法内部,我们将 left 初始化为 0(第一个字符的索引),将 right 初始化为 str.length() - 1(最后一个字符的索引)。
  • while (left < right) 循环会一直执行,只要左指针在右指针的左侧。
  • if (str.charAt(left) != str.charAt(right)) 比较当前 leftright 位置的字符。如果它们不同,我们立即知道这不是回文串,并返回 false
  • 如果字符匹配,我们将指针向内移动:left++ 使左指针递增,right-- 使右指针递减。
  • 如果循环结束时没有返回 false,这意味着所有比较的字符都匹配,因此该字符串是回文串,我们返回 true
  • main 方法中,我们使用不同的测试字符串调用 checkPalindrome 方法,并打印结果。

保存 PalindromeChecker.java 文件。

现在,在终端中编译并运行该程序:

javac PalindromeChecker.java
java PalindromeChecker

你应该会看到以下输出:

"madam" is a palindrome.
"racecar" is a palindrome.
"hello" is not a palindrome.

这展示了双指针法如何在不反转整个字符串的情况下高效地检查回文串。

在回文检查中忽略大小写和非字母字符

在上一步中,我们的回文检查器适用于像 "madam" 和 "racecar" 这样的简单字符串。然而,现实世界中的回文通常会忽略大小写和标点符号。例如,"A man, a plan, a canal: Panama" 被认为是一个回文。

在这一步中,我们将增强 PalindromeChecker 程序,使其能够处理这些情况,即忽略非字母字符,并将大写字母和小写字母视为相同。

在 WebIDE 编辑器中打开 PalindromeChecker.java 文件。我们将修改 checkPalindrome 方法。

将现有的 checkPalindrome 方法替换为以下更新后的版本:

    // Method to check if a string is a palindrome using two pointers,
    // ignoring case and non-letter characters
    public static boolean checkPalindrome(String str) {
        // Initialize two pointers
        int left = 0; // Pointer starting from the beginning
        int right = str.length() - 1; // Pointer starting from the end

        // Loop while the left pointer is less than the right pointer
        while (left < right) {
            // Move left pointer past non-letter characters
            while (left < right && !Character.isLetter(str.charAt(left))) {
                left++;
            }

            // Move right pointer past non-letter characters
            while (left < right && !Character.isLetter(str.charAt(right))) {
                right--;
            }

            // If left and right pointers haven't crossed and characters don't match (ignoring case)
            if (left < right && Character.toLowerCase(str.charAt(left)) != Character.toLowerCase(str.charAt(right))) {
                // If characters don't match, it's not a palindrome
                return false;
            }

            // Move the pointers inwards
            left++;
            right--;
        }

        // If the loop completes without finding any mismatch, it's a palindrome
        return true;
    }

以下是我们所做的更改:

  • 我们在主 while (left < right) 循环内部添加了两个 while 循环。
  • 第一个内部 while 循环 (while (left < right && !Character.isLetter(str.charAt(left)))) 会将 left 指针向前移动,只要它仍然在 right 指针的左侧,并且 left 指针所指的字符 不是 字母 (!Character.isLetter(...))。
  • 第二个内部 while 循环 (while (left < right && !Character.isLetter(str.charAt(right)))) 会将 right 指针向后移动,只要它仍然在 right 指针的左侧,并且 right 指针所指的字符 不是 字母。
  • 比较语句 if (left < right && Character.toLowerCase(str.charAt(left)) != Character.toLowerCase(str.charAt(right))) 现在包含两个重要的检查:
    • left < right:这确保了只有在跳过非字母字符后指针没有交叉时,我们才会比较字符。
    • Character.toLowerCase(...):这会在比较两个字符之前将它们都转换为小写,从而有效地忽略大小写。
  • 如果字符(转换为小写后)不匹配,我们返回 false
  • 如果它们匹配,我们将两个指针向内移动 (left++, right--) 以检查下一对字符。

现在,让我们修改 main 方法,用一个包含空格、标点符号和大小写混合的字符串进行测试。将 main 方法中现有的测试用例替换为以下内容:

    public static void main(String[] args) {
        String testString = "A man, a plan, a canal: Panama"; // A classic palindrome
        boolean isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "No 'x' in Nixon"; // Another palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "hello world"; // Not a palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }
    }

保存 PalindromeChecker.java 文件。

在终端中编译并运行更新后的程序:

javac PalindromeChecker.java
java PalindromeChecker

你现在应该会看到以下输出,即使字符串包含非字母字符和大小写混合,也能正确识别回文:

"A man, a plan, a canal: Panama" is a palindrome.
"No 'x' in Nixon" is a palindrome.
"hello world" is not a palindrome.

你已经成功增强了回文检查器,使其能够处理更复杂的字符串!

总结

在这个实验中,我们学习了如何在 Java 中检查一个字符串是否为回文串。我们首先实现了一个反转字符串的方法,并将其与原始字符串进行比较,以此来判断它是否为回文串。这包括创建一个 Java 文件、编写代码以反向遍历字符串,以及使用 equals() 方法进行比较。

然后,我们探索了双指针法,这是一种更高效的回文检查方法,它避免了创建一个新的反转字符串。最后,我们增强了回文检查功能,使其能够忽略大小写和非字母字符,从而使检查在现实场景中更加可靠。