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語言的解法中,該算法並非最優解。

除此以外,還有另一種思路,就是將鏈表拆分紅兩部分,而後使得一部分反轉,後遍歷兩個鏈表,觀察是否相等。可是,該方法通過博主測試後,發現其效率還不如上述解法高效,所以不在敘述,後續若是有新的更高效解法在來敘述。

相關文章
相關標籤/搜索