1. 程式人生 > >22 鏈表中倒數第k個節點(第3章 高質量的代碼-代碼的魯棒性)

22 鏈表中倒數第k個節點(第3章 高質量的代碼-代碼的魯棒性)

== 了解 public bsp null 另一個 struct text 方法

題目描述:

輸入一個鏈表,輸出該鏈表中倒數第k個結點。

尾節點是倒數第一個節點

測試用例:

功能測試(第k個節點在中間、是頭節點、是尾節點)

特殊輸入測試(鏈表頭節點是nullptr指針、鏈表的頭節點個數小於k、k=0)

解題思路:

1)使用兩個指針,一個指針先移動k步,如果鏈表小於k,終止返回nullptr。然後兩個指針同時移動,知道後一個指針移出最後一個節點

//實現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; //不要忘記k<0的情況 無符號不用判斷k<0時; ListNode* back = pListHead; //先將指針back移動到第k個元素的位置,索引k的位置 while(back!=nullptr && k>0){ //先判斷k=0,然後才是k--。 back=back->next; k--; } if(k>0) //說明鏈表的長度<k return nullptr; ListNode* front = pListHead; while(back!=nullptr){ //back->next!=nullptr 是錯誤的。 back=back->next; front=front->next; } return front; } };  

註:尾節點是倒數第一個節點,因此k=1時,front應該指向尾節點,此時back應該是剛好移出尾節點,為空nullptr。

使用兩個指針,一個指針先移動k-1步,如果鏈表小於k,終止返回nullptr。然後兩個指針同時移動,知道後一個指針移動到最後一個節點

//實現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;  //無符號,所以不用判斷k<0;
        
        ListNode* back = pListHead;
        //先將指針back移動到第k-1個元素的位置,
        while(back->next!=nullptr && k-1>0){ //為了得知第k個元素是否存在,應該判斷back->next!=nullptr而不是back!=nullptr
            back=back->next;
            k--;
        }
        if(k>1) //說明鏈表的長度<k
            return nullptr;
        
        ListNode* front = pListHead;
        while(back->next!=nullptr){ //back移動到最後一個元素即可
            back=back->next;
            front=front->next;
        }
        
        return front;
    }
};
//實現2
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==nullptr || k==0)return nullptr;  //無符號,所以不用判斷k<0;
        
        ListNode* back = pListHead;
        //先將指針back移動到第k-1個元素的位置,
        /*while(back->next!=nullptr && k-1>0){ //為了得知第k個元素是否存在,應該判斷back->next!=nullptr而不是back!=nullptr
            back=back->next;
            k--;
        }
        if(k>1) //說明鏈表的長度<k
            return nullptr;*/
        for(unsigned int i=0;i<k-1;++i){
            if(back->next!=nullptr)
                back=back->next;
            else
                return nullptr;
        }
        
        ListNode* front = pListHead;
        while(back->next!=nullptr){ //back移動到最後一個元素即可
            back=back->next;
            front=front->next;
        }
        
        return front;
    }
};

    

對於unsigned int類型要格外註意,在寫循環或者判斷時,常會遇到對變量--;這種情況要格外註意:

因為當unsigned int k=0; --k後,變量的值並不是-1,而是無符號的0xFFFFFFFF,如果此時判斷k>0,還是會成立

//該方法是錯誤的,當k=0是,K-1為0xFFFFFFFF,back會一直向後訪問超出數組
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==nullptr || k<0)return nullptr;
        
        ListNode* back = pListHead;
        //先將指針back移動到第k-1個元素的位置
       for(unsigned int i=0; i<k-1; ++i){
            bask=back->next;
        }

        if(k>1) //說明鏈表的長度<k
            return nullptr;
        
        ListNode* front = pListHead;
        //back移動到最後一個元素
        while(back->next!=nullptr){ //back->next!=nullptr
            back=back->next;
            front=front->next;
        }
        
        return front;
    }
};

  

相似題目:

求鏈表的中間節點:如果鏈表中的節點總數為奇數,則返回中間節點;如果鏈表總數是偶數,則返回中間兩個節點的任意一個。

為了解決這個問題,也可以同時定義兩個指針,同時從鏈表出發,一個指針一次走一步,另一個指針一次走兩步。當走的快的指針走到鏈表末尾時,走的慢的指針正好在鏈表的中間。

22 鏈表中倒數第k個節點(第3章 高質量的代碼-代碼的魯棒性)