leetcode面试题 02.06. 回文链表,解题心路

leetcode面试题 02.06. 回文链表,解题心路

一、题目描述

编写一个函数,检查输入的链表是不是回文的。如图:面试

试题连接:https://leetcode-cn.com/problems/palindrome-linked-list-lcci/算法

二、java语言题解一

看到该题,首先想打到的就是使用本身最拿手的语言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的提交记录中,时间稍微较慢,当时所须要的内存确实最少的。然而,计算机程序比较关心的是算法的执行效率,所以该算法还得进行改进。测试

三、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来做答,所以,只有用C语言重写上述的java算法。

  1. 先来看看在C语言中,题目给出的链表的结构题类型
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语言的解法中,该算法并非最优解。

除此以外,还有另一种思路,就是将链表拆分红两部分,而后使得一部分反转,后遍历两个链表,观察是否相等。可是,该方法通过博主测试后,发现其效率还不如上述解法高效,所以不在叙述,后续若是有新的更高效解法在来叙述。

相关文章
相关标签/搜索