啊哈算法之巧用栈解密回文字符串

简述

本算法摘选自啊哈磊所著的《啊哈!算法》第二章第二节的题目——使用栈来解密回文。文中代码使用C语言编写,博主通过阅读和理解,重新由Java代码实现了一遍,意在深刻理解栈这一数据结构的特性和操作方法,并希望能够在这种数据结构的帮助之下,解决其他的类似的能够用栈来解决的问题。(哈哈,偷懒了,引用了上一篇博文的简述)

算法题目

回文字符串就是正读反读均相同的字符串序列,比如“xyzyx”、“aha”、”ahaha”和“121”等等,现在要求你使用算法来判断给定一个字符串是否是回文字符串。

解题思路

如果一个字符串是回文的话,那么它肯定是中间对称的,只需要将中间点以前的字符串反过来与中间点后面的字符串一一比较,如果都相等,那么就是回文字符串了,那么如何能够将中间点前面的字符串依次读入然后再反过来读出呢,这个时候栈就上场了。

栈是一种后进先出的数据结构,只能在一端进行插入和删除操作,就如同手枪弹夹一样,装子弹的时候总是在弹夹的异端塞入,而且最后装入的那发子弹会最先打出,最先装入的字段成了最后一发,弹夹的结构就类似于栈的原理结构。把回文字符串顺着放进栈中,能够倒着顺序取出来,这刚好就满足了我们的需求,栈的实现也很简单,只需要一个一维数组和一个指向栈顶的指针(变量)top,我们在插入或者删除栈中数据时移动top指针就行了,这样我们就能很容易的接用栈这种数据结构来判断字符串是否是回文了,接下来我们看具体的代码实现。

代码实现

 1 public static void main(String[] args) {
 2     // 假设一段字符串
 3     String str = "xyzzyx";
 4     char[] cha = str.toCharArray();
 5 
 6     // 使用数组模拟栈
 7     char[] stack = new char[10];
 8 
 9     // 求字符串的中点
10     int len = str.length();
11     int mid = len / 2;
12 
13     // 栈的开始位置
14     int top = 0;
15 
16     // 将字符串的前半段依次入栈
17     for(int i = 0; i < mid; i++) {
18         stack[top] = cha[i];
19 
20         // 栈顶指针上移(下面的代码可以合入到上面一行,这里为方便理解)
21         top++;
22     }
23 
24     // 判断字符串长度是奇数还是偶数,并决定需要匹配字符串开始下标
25     int next = (len & 1) == 0 ? mid : (mid + 1);
26 
27     // 开始匹配
28     for(int j = next; j < len; j++) {
29         // 利用栈的原理,出栈顺序的字符串和入栈顺序是相反的,所以如果出栈顺序和字符串后半段顺序是一致的,则说明是回文
30         if(cha[j] != stack[--top]) {
31             break;
32         }
33     }
34 
35     // 如果top最后的值为0,则说明栈内所有内容都匹配上了,结果就是回文
36     if(top == 0) {
37         System.out.println("Yes, it is HW.");
38     }else {
39         System.out.println("No, it is not HW.");
40     }
41 }

总结

栈的特性很容易理解就是后进先出(Last In First Out, LIFO),实现上只需要用一个一维数组和一个变量top封装起来就行了,出栈和入栈的操作只需要移动栈顶指针即变量top即可,当变量top的值等于0时,则说明当前栈是一个空栈。堆栈的概念最早由Alan M.Turing(艾伦·图灵)提出的,意在解决子程序的调用和返回,熟悉Java底层概念的同学对此应该都有所了解吧。

参考资料

1、《啊哈!算法》/ 啊哈磊著. 人民邮电出版社

点赞