鏈表中倒數第k個節點 棧 雙指針 擴展:尋找鏈表的中間節點

傳送門

分析:

       首先,這道題考察了程序的魯棒性,主要是關於空指針以及k的取值問題

       第一種思路:可以使用一個棧來實現,由於棧是後進先出的一種數據結構,我們可以將遍歷鏈表的節點存儲到棧中,接着彈棧k次即可得到倒數第k個節點。

       第二種思路:雙指針

              我們考慮設置兩個指針,開始時都指向頭結點,第一個指針向前移動k-1次,這樣它就到達了第k個節點,第二個指針指向頭結點,它們相距k-1步,接着同時移動兩個指針,直至第一個指針指向尾節點,這樣第二個指針就指向倒數第k個節點。

棧:

//可以把鏈表放到棧中,然後逆向彈出第k個元素即爲倒數第k個節點
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==nullptr) return nullptr;
        stack<ListNode*>solve;
        while(!solve.empty()) solve.pop();
        ListNode* pNode = new ListNode(-1);
        pNode = pListHead;
        while(pNode!=nullptr)
        {
            solve.push(pNode);
            pNode = pNode->next;
        }
        ListNode* num = new ListNode(-1);
        if(k>solve.size()||k==0) return nullptr;
        while(k--)
        {
            num = solve.top();
            solve.pop();
        }
        return num;
    }
};

雙指針:

//第一種思路:是使用一個棧來儲存鏈表從前向後遍歷的節點,然後經歷k次彈棧即可
//第二種思路:使用雙指針,設置兩個指針,首先都指向頭結點,接着第一個指針向前移動k步
//那麼第二個指針與第一個指針相差k-1步,這樣,當第一個指針指向尾節點,那麼第二個指針就指向解
//第二種方法比較巧妙
/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==nullptr||k==0) return nullptr;
        ListNode* First = pListHead;
        ListNode* Second = pListHead;
        for(int i=0;i<k-1;i++)
        {
            First = First->next;
            if(First==nullptr) return nullptr;
        }
        while(First->next!=nullptr)
        {
            First = First->next;
            Second = Second->next;
        }
        return Second;
    }
};

擴展:尋找鏈表的中間節點

分析:我們可以定義兩個指針,同時從鏈表的頭結點出發,一個指針一次走一步,另一個指針一次走兩步,當走得快的指針走到鏈表的末尾時,走得慢的指針正好在鏈表的中間。

當我們用一個指針遍歷鏈表不能解決問題的時候,可以嘗試用兩個指針來遍歷鏈表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章