简介
在这个实验中,你将学习如何在 Java 中检查一个字符串是否为回文串。我们将探讨不同的方法,首先是反转字符串并将其与原始字符串进行比较的基本方法。
在此基础上,你将学习使用双指针法的更高效技术。最后,我们将改进回文检查,使其忽略大小写和非字母字符,从而使检查更加可靠。
在这个实验中,你将学习如何在 Java 中检查一个字符串是否为回文串。我们将探讨不同的方法,首先是反转字符串并将其与原始字符串进行比较的基本方法。
在此基础上,你将学习使用双指针法的更高效技术。最后,我们将改进回文检查,使其忽略大小写和非字母字符,从而使检查更加可靠。
在这一步中,我们将首先创建一个简单的 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";
:我们声明了一个名为 originalString
的 String
变量,并将其赋值为 "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()
方法比较 originalString
和 reversedString
。在 Java 中,你应该使用 equals()
方法来比较字符串的内容,而不是 ==
运算符。if
和 else
代码块根据字符串是否相同打印不同的消息。保存 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))
比较当前 left
和 right
位置的字符。如果它们不同,我们立即知道这不是回文串,并返回 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()
方法进行比较。
然后,我们探索了双指针法,这是一种更高效的回文检查方法,它避免了创建一个新的反转字符串。最后,我们增强了回文检查功能,使其能够忽略大小写和非字母字符,从而使检查在现实场景中更加可靠。