LeetCode題目描述:移除鏈表元素
刪除鏈表中等於給定值 val 的所有節點。
示例:
輸入: 1->2->6->3->4->5->6, val = 6
輸出: 1->2->3->4->5
解題思路:首先保證鏈表不爲空(代碼3-6行),由於鏈表首元素未判斷(題目給的鏈表爲不帶頭結點鏈表),因此第一步先找到到第一個數據不等於val的節點(代碼8-24行)。第二步再對鏈表中的每個節點的數據進行判斷,因爲要刪除節點,所以需要每次判斷後繼節點數據和val值,如果後繼節點需要刪除,則遍歷指針不後移,若不刪除後繼指針,則遍歷指針繼續向後遍歷
當然還有操作更簡單的創建頭指針法解決,具體可以看下一道題的另一種方法實現!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
if(head==NULL)
{
return NULL;
}
struct ListNode* cur=head;
while(1)
{
if(cur==NULL)//當鏈表中只有被刪元素時,前面刪除完之後鏈表爲空
{
return NULL;
}
if(cur->val==val)
{
struct ListNode*tmp=cur;
cur=cur->next;
free(tmp);
}
else
{
break;//cur結點不爲空且cur結點的數據與val不等
}
}
head=cur;
for(;cur->next!=NULL;)
{
if(cur->next->val == val)
{
struct ListNode* tmp=cur->next;
cur->next=cur->next->next;
free(tmp);
}
else
{
cur=cur->next;
}
}
return head;
}
圖解:
範例 6->6->1->2->6->3->4->5->6
LeetCode題目描述:刪除重複節點
在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。
例如,
鏈表1->2->3->3->4->4->5
處理後爲 1->2->5**
思路分析:本題其實是上一個題的變種。只不過這次的val值是變化的,只要重複該節點,則val=node->val;
首先判斷每個節點和後續節點是否重複,若重複就保存該節點的val值,然後不斷刪除後面和val值相同的節點,直到遇到和val不同的節點,說明刪除完畢,接着下次判斷。
若不重複就繼續向後遍歷判斷。
這裏有一個開始困擾的情況就是如果頭結點就是重複節點,那麼該如何刪除全部重複節點?
這裏有兩種解決辦法:
- 先不斷刪除頭部重複節點,直到找到第一個不重複的節點作爲結束時返回的頭結點,若在刪除過程中遇到NULL說明該鏈表中所有節點均有重複;然後再對後繼節點和後繼next節點的next值判斷,若val值相同,則按照上面的解題思路刪除重複節點即可
- 另一種就是爲了統一操作,申請一個新節點作爲頭結點,直接按照上面的解題思路遍歷就Ok了。
這裏代碼給出來兩種方法的代碼實現:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
int data=0;
if(pHead==NULL)
{
return NULL;
}
ListNode *cur=pHead;
ListNode*tmp=NULL;
for(;cur!=NULL&&cur->next!=NULL;)//頭結點就出現元素重複,先找到第一個不重複的節點
{
if(cur->val==cur->next->val)//節點重複
{
data=cur->val;
while(cur!=NULL&&cur->val==data)
{
//刪除cur節點及之後與cur數據重複的節點
tmp=cur;
cur=cur->next;
free(tmp);
}
if(cur==NULL)
{
return NULL;
}
}
else
{
break;//cur和cur->next的數據不重複,說明cur節點爲第一個不重複節點
}
}
pHead=cur;
for(;cur!=NULL&&cur->next!=NULL&&cur->next->next!=NULL;)
{
if(cur->next->val==cur->next->next->val)//判斷cur的後繼節點是否爲重複節點
{
data=cur->next->val;
while(cur->next!=NULL && cur->next->val==data)
{
//刪除cur之後和data相同的節點
tmp=cur->next;
cur->next=cur->next->next;
free(tmp);
}
}
else
{
cur=cur->next;
}
}
return pHead;
}
};
創建頭結點解法:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL)
{
return NULL;
}
int data;
ListNode*cur=(ListNode*)malloc(sizeof(ListNode));//創建一個頭結點,防止傳入的頭結點就存在重複的情況
cur->next=pHead;
ListNode*head=cur;//記錄頭結點,防止cur遍歷後丟失頭結點
ListNode*tmp=NULL;
while(cur->next!=NULL&&cur->next->next!=NULL)
{
if(cur->next->val==cur->next->next->val)
//對cru之後的節點進行判斷,如果重複,進入內部循環刪除和data相同值的節點
{
data=cur->next->val;
while(cur->next!=NULL&&cur->next->val==data)//刪除和data數據相同的cur->next
{
tmp=cur->next;
cur->next=cur->next->next;
free(tmp);
tmp=NULL;
}
}
else
{
cur=cur->next;
}
}
pHead=head->next;
free(head);//釋放19行創建的新節點
return pHead;
}
};
以創建頭結點法爲例作以圖解:
用例:1->1->1->2->2->3->4->4->5
LeetCode題目描述:反轉一個鏈表
反轉一個單鏈表。
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
解題思路:
採用指針指向掉頭的方法迭代實現,需要注意保存每次掉頭的新鏈表頭結點和舊鏈表的頭結點,,然後每次需要一個指針記錄即將調轉指向節點的後繼節點
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
if(head==NULL)
{
return;
}
struct ListNode* cur=head->next;
struct ListNode* tmp=head;
tmp->next=NULL;
while(cur!=NULL)
{
struct ListNode*p=cur->next;
cur->next=tmp;
tmp=cur;
cur=p;
}
head=tmp;
return head;
}
圖解: