编写一个函数,检查输入的链表是不是回文的。如图:面试
试题连接:https://leetcode-cn.com/problems/palindrome-linked-list-lcci/算法
看到该题,首先想打到的就是使用本身最拿手的语言java来作。首先,咱们先来观查题目所给链表的结构:数组
class ListNode { int val; ListNode next; ListNode(int x) { val = x; } }
因为题目中要求判断一个链表是否回文,所以很天然的一个想法就是,将链表变量,取出其中的值,放在一个有序的容器中。在java中很天然的就想到了list集合,因而就有了下述的解法:数据结构
public static boolean isPalindrome(ListNode head) { List list = new ArrayList(); //定义一个辅助指针,用来遍历链表 ListNode pCurrent = head; //当链表不为null时,就一直循环 while (pCurrent != null) { //将该数保存到数组中 list.add(pCurrent.val); pCurrent = pCurrent.next; } //遍历集合,看首尾是否相等 for(int i = 0;i < list.size() / 2;i++) { if(!list.get(i).equals(list.get(list.size() - i - 1))) { return false; } } return true; }
算法效果:函数
能够看出,该算法在java的提交记录中,时间稍微较慢,当时所须要的内存确实最少的。然而,计算机程序比较关心的是算法的执行效率,所以该算法还得进行改进。测试
因为上述的算法的执行时间太长,猜测是否是由于使用了List集合而致使的。可是,若是不适用集合,咱们的先获取到该链表的长度,而后定义一个大小刚刚适合的数组。代码以下:3d
public static boolean isPalindrome(ListNode head) { //定义一个辅助指针,用来遍历链表 ListNode pCurrent = head; //当链表不为null时,就一直循环 int count = 0; while (pCurrent != null) { //计数 count++; pCurrent = pCurrent.next; } //再来一论,装进数组 pCurrent = head; int[] arr = new int[count]; for(int i = 0;i < count;i++) { arr[i] = pCurrent.val; pCurrent = pCurrent.next; } //遍历集合,看首尾是否相等 for(int i = 0;i < count / 2;i++) { if(arr[i] != arr[count - i - 1]) { return false; } } return true; }
算法效果:指针
能够看出,用数组代替集合,增长一次循环后的效率获得大幅度的提高。code
奈何,博主目前仍是一个本科大学生,在数据结构与算法这门课上垂死挣扎,而考试只容许用C来做答,所以,只有用C语言重写上述的java算法。
struct ListNode { int val; struct ListNode *next; };
接下来,用C语言来实现上述的java题解二:
bool isPalindrome(struct ListNode* head){ //定义一个辅助指针,用来遍历链表 struct ListNode* pCurrent = head; //当链表不为null时,就一直循环 int count = 0; while (pCurrent != NULL) { //计数 count++; pCurrent = pCurrent->next; } if(count == 0) return true; //再来一论,装进数组 pCurrent = head; int arr[count]; for(int i = 0;i < count;i++) { arr[i] = pCurrent->val; pCurrent = pCurrent->next; } //遍历集合,看首尾是否相等 for(int i = 0;i < count / 2;i++) { if(arr[i] != arr[count - i - 1]) { return false; } } return true; }
算法效果:
由执行用时能够看出,在C语言的解法中,该算法并非最优解。
除此以外,还有另一种思路,就是将链表拆分红两部分,而后使得一部分反转,后遍历两个链表,观察是否相等。可是,该方法通过博主测试后,发现其效率还不如上述解法高效,所以不在叙述,后续若是有新的更高效解法在来叙述。