22 鏈表中倒數第k個節點(第3章 高質量的代碼-代碼的魯棒性)
阿新 • • 發佈:2019-02-28
== 了解 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章 高質量的代碼-代碼的魯棒性)