一,刪除排序鏈表中的重複元素(83題)
題目要求:給定一個排序鏈表,刪除所有重複的元素,使得每個元素只出現一次。
解題思路:1,首先判斷鏈表是否爲空,如果爲空,返回空
2,是否只有一個元素,如果只有一個元素,返回head
3,循環遍歷鏈表,刪除值和它之前結點相等的結點,注意,將每一個結點都和它之前的結點進行比較
代碼實現:
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head == NULL || head->next == NULL) {
return head;
}
//如果鏈表爲空,返回head
//如果鏈表只有一個元素,返回head;
//否則,遍歷循環,刪除後面的元素,接着判斷是否繼續刪除
struct ListNode* cur = head;
while(cur->next != NULL) {
struct ListNode* next = cur->next;
if(cur->val == cur->next->val) {
cur->next = cur->next->next;
free(next);
continue;
}
cur = cur->next;
}
return head;
}
二:刪除排序鏈表中的重複元素 II(82題)
題目要求:給定一個排序鏈表,刪除所有含有重複數字的節點,只保留原始鏈表中 沒有重複出現 的數字。
解題思路:1,首先判斷鏈表是否爲空
2,申請一個結點node,作爲原鏈表的起始結點,
3,定義三個指針,prev cur next 分別指向node , head , head->next
4,判斷二三結點值是否相等,
5,如果不相等,所有指針往後挪,繼續判斷,
6,如果相等,第三個指針往後挪,
7,繼續判斷,直到不相等爲止,將prev->next 改爲 next 將cur 改爲next,將next改爲next->next;
8,將cur指向node->next
9,釋放掉node ,返回cur
10,注意:此處沒有考慮重複結點的釋放問題
代碼實現:
struct ListNode* deleteDuplicates(struct ListNode* head) {
if (head == NULL || head->next == NULL) {
return head;
}
struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
node->next = head;
struct ListNode* prev = node;
struct ListNode* cur = head;
struct ListNode* next = head->next;
while (next != NULL) {
if (cur->val != next->val) {
prev = cur;
cur = next;
next = next->next;
}
else {
while (next != NULL && next->val == cur->val) {
next = next->next;
}
prev->next = next;
cur = next;
if (next != NULL) {
next = next->next;
}
}
}
cur = node->next;
free(node);
return cur;
}
三:複製帶隨機指針的鏈表(138題)
題目要求:
給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點。
要求返回這個鏈表的深拷貝。
題目解釋:每個結點指針域裏面都有三個值,一個結點的值,一個保存指向下一個結點的指針,一個保存該結點指向隨機結點的指針。
例如:該圖中,1結點的值爲1,next指向2結點,random指向2結點,2結點的值爲2,next指向NULL,random指向自己,
題目要求爲將這樣一個複雜鏈表複製一份,返回的鏈表和原鏈表一樣。
解題思路:1,首先判斷鏈表是否爲空,
2,如果爲空,返回空
3,往每個結點後創建一個新結點,
4,設置新結點的random
5,拆分鏈表,返回新鏈表
代碼實現:
class Node {
public:
int val;
Node* next;
Node* random;
Node() {}
Node(int _val, Node* _next, Node* _random) {
val = _val;
next = _next;
random = _random;
}
};
class Solution {
public:
Node* copyRandomList(Node* head) {
if (head == NULL) {
return head;
}
Node* cur = head;
while (cur != NULL) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->val = cur->val;
newNode->random = NULL;
newNode->next = cur->next;
cur->next = newNode;
cur = newNode->next;
}
cur = head;
while (cur != NULL) {
if (cur->random != NULL) {
cur->next->random = cur->random->next;
}
cur = cur->next->next;
}
cur = head;
Node* newHead = head->next;
while (cur != NULL) {
Node* newNode = cur->next;
cur->next = newNode->next;
if (newNode->next != NULL) {
newNode->next = newNode->next->next;
}
cur = cur->next;
}
return newHead;
}
};
四:刪除鏈表的倒數第N個節點(19題)
題目要求:給定一個鏈表,刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。
解題思路:
1,首先判斷鏈表是否爲空,如果爲空,返回NULL
2,定義快慢指針,fast slow
3,快指針先走n步, 並且不能爲空(fast != NULL &&n > 0)
4,接下來判斷fast可能退出的幾個條件
(1)如果因爲fast == NULL並且n沒有減到0退出,說明,要刪除的結點不符合要求,
將原鏈表返回,return head;
(2)如果因爲fast == NULL 並且n 剛好減到 0 , 說明要刪除的結點爲第一個結點,保存第二個結點的地址
釋放第一個結點的空間,返回第二個結點的地址。
(3)fast先走了n步,然後,slow和fast同時走,直到fast->next == NULL
這時說明slow->next 即爲要刪除的結點,將slow->next結點保存記爲next結點,將slow->next改爲slow->next->next
5,最後一步釋放next結點,返回head
代碼實現:
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
if (head == NULL) {
return NULL;
}
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast != NULL && n > 0) {
n--;
fast = fast->next;
}
if (fast == NULL && n != 0) {
return head;
}
else if (fast == NULL && n == 0) {
struct ListNode* next = head->next;
free(head);
return next;
}
while (fast->next != NULL && slow != NULL) {
fast = fast->next;
slow = slow->next;
}
struct ListNode* next = slow->next;
slow->next = slow->next->next;
free(next);
return head;
}
五:環形鏈表 II(142題)
題目要求:給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null
。
解題思路:1,給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。
2,首先判斷鏈表是否爲空,如果爲空,返回空
3,定義兩個指針,快慢指針fast slow,
4,快指針每次走兩步,慢指針每次走一步
5,用一個do while循環,一步一步走判斷是否爲空,如果爲空,退出循環,返回空
6,否則直到快慢指針相遇,結束循環,說明鏈表有環,
7,定義兩個指針分別指向head 和 fast 的位置,
8,使用循環找到相遇點,返回該結點。
代碼實現:
struct ListNode *detectCycle(struct ListNode *head) {
if (head == NULL) {
return NULL;
}
struct ListNode *fast = head;
struct ListNode *slow = head;
do {
fast = fast->next;
if (fast == NULL){ break; }
fast = fast->next;
if (fast == NULL){ break; }
slow = slow->next;
} while (slow != fast);
if (fast == NULL) {
return NULL;
}
struct ListNode *p1 = head;
struct ListNode *p2 = fast;
while (p1 != p2) {
p1 = p1->next;
p2 = p2->next;
}
return p1;
}