赞
踩
题目要求:
解析:
prev->next = cur->next
,free(cur)
(只有当头结点不为空且不需要删除时,才会用到prev指针)。//code-1: struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* cur = head; //1.特殊情况,链表为空 if(cur == NULL) return head; //2.特殊情况,链表中的所有结点的val都等于目标值,需全部删除 while(cur && cur->val == val) { struct ListNode* del = cur; cur = cur->next; free(del); //del是局部变量,不需要再置空 } //更新头结点 head = cur; //出2的循环时,要么cur为空,要么cur->val!=val //3.常规情况 struct ListNode* prev = cur; //prev->val!=val if(prev) { cur = prev->next; //如果要删除,就删除cur结点 while(cur) { //需要删除 if(cur->val == val) { prev->next = cur->next; free(cur); cur = prev->next; } else { prev = cur; cur = cur->next; } } } return head; }
算法复杂度: 时间复杂度O(n),空间复杂度O(1)。
prev->next = cur->next
,free(cur)
。再更新cur。//code-2 struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* cur = head; struct ListNode* prev = NULL;//指向要删除结点的上一个结点 while(cur) { //需要删除当前结点 if(cur->val == val) { //需要删除的结点是头结点 if(cur == head) { head = head->next; free(cur); cur = head; } else//删除非头节点 { //常规情况的删除 prev->next = cur->next; free(cur); cur = prev->next; } } else { prev = cur; cur = cur->next; } } return head; }
算法复杂度: 时间复杂度O(n),空间复杂度O(1)。
//code-1: 不带哨兵位结点 struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* newHead, *tail; newHead = tail = NULL; struct ListNode* cur = head; while(cur) { if(cur->val != val) { if(tail == NULL) { newHead = tail = cur; } else { tail->next = cur; tail = tail->next; } cur = cur->next; } else { struct ListNode* del = cur; cur = cur->next; free(del);//局部变量,不需要再置为空 } } //新链表结尾置为空 if(tail)//防止解引用空指针 tail->next = NULL; return newHead; }
//code-2: 带哨兵位结点 (推荐) struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* cur = head; struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode)); assert(guard); struct ListNode* tail = guard; while(cur) { if(cur->val != val) { tail->next = cur; cur = cur->next; tail = tail->next; } else { struct ListNode* del = cur; cur = cur->next; free(del); } } //注意,一定要判断tail是否为空 if(tail) tail->next = NULL; head = guard->next; free(guard); return head; }
算法复杂度: 时间复杂度:O(n),空间复杂度:O(1)。
题目要求:
解析:
法一:
struct ListNode* reverseList(struct ListNode* head){ //head为空,或head->next为空,就没必要反转 if(!head || !head->next) { return head; } struct ListNode* cur = head->next; struct ListNode* newHead = head; while(cur) { head->next = cur->next; cur->next = newHead; newHead = cur; cur = head->next; } return newHead; }
算法复杂度: 时间:O(n),空间O(1)。
法二(推荐):
反转“指针”。
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* prev = NULL, *cur = head;
while(cur)
{
struct ListNode* next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
算法复杂度: 时间:O(n),空间:O(1)。
题目要求:
解析:
struct ListNode* middleNode(struct ListNode* head){
struct ListNode* fast, *slow;
fast = slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
算法复杂度: 时间:O(n),空间:O(1)。
题目要求:
解析:
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) { struct ListNode* fast, *slow; fast = slow = pListHead; //先让fast走k步 while(fast && k--) { fast = fast->next; } //k>链表长度 if(k > 0) return NULL; while(fast) { fast = fast->next; slow = slow->next; } return slow; }
算法复杂度: 时间:O(n),空间:O(1)。
题目要求:
解析:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){ struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode)); assert(guard); guard->next = NULL; struct ListNode* tail = guard; struct ListNode* cur1 = list1, *cur2 = list2; while(cur1 && cur2) { if(cur1->val < cur2->val) { tail->next = cur1; tail = tail->next; cur1 = cur1->next; } else { tail->next = cur2; tail = tail->next; cur2 = cur2->next; } } if(cur1) { tail->next = cur1; } if(cur2) { tail->next = cur2; } return guard->next; }
算法复杂度: 时间:O(n),空间O(1)。
题目要求:
解析:
class Partition { public: ListNode* partition(ListNode* pHead, int x) { struct ListNode* LessGuard, *LessTail, *GreaterGuard, *GreaterTail; LessGuard = (ListNode*)malloc(sizeof(ListNode)); GreaterGuard = (ListNode*)malloc(sizeof(ListNode)); assert(LessGuard && GreaterGuard); LessTail = LessGuard; GreaterTail = GreaterGuard; GreaterTail->next = LessTail->next = NULL;//也可以不写 ListNode* cur = pHead; while(cur) { if(cur->val < x) { LessTail->next = cur; LessTail = LessTail->next; //cur = cur->next; } else { GreaterTail->next = cur; GreaterTail = GreaterTail->next; //cur = cur->next; } cur = cur->next; } LessTail->next = GreaterGuard->next; GreaterTail->next = NULL;//注意,这一步不能省略 pHead = LessGuard->next; free(LessGuard); free(GreaterGuard); return pHead; } };
算法复杂度: 时间:O(n),空间O(1)。
题目要求:
解析:
//找中间结点 struct ListNode* middleNode(struct ListNode* head){ struct ListNode* fast, *slow; fast = slow = head; while(fast && fast->next) { slow = slow->next; fast = fast->next->next; } return slow; } //翻转链表 struct ListNode* reverseList(struct ListNode* head){ struct ListNode* prev = NULL; struct ListNode* cur = head; while(cur) { struct ListNode* next = cur->next; cur->next = prev; prev = cur; cur = next; } return prev; } bool isPalindrome(struct ListNode* head){ struct ListNode* mid = middleNode(head); struct ListNode* rmid = reverseList(mid); struct ListNode* cur = head; while(cur && rmid) { if(cur->val != rmid->val) return false; cur = cur->next; rmid = rmid->next; } return true; }
算法复杂度: 时间:O(n),空间:O(1)。
题目要求:
解析:
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) { if (!headA || !headB) return NULL; struct ListNode* cur1 = headA; struct ListNode* cur2 = headB; int len1 = 1; int len2 = 1; //找尾结点,并记录链表长度 while (cur1->next) { cur1 = cur1->next; len1++; } while (cur2->next) { cur2 = cur2->next; len2++; } //两链表不交叉 if (cur1 != cur2) { return NULL; } // struct ListNode* LongList = headA; struct ListNode* ShortList = headB; if (len1 < len2) { LongList = headB; ShortList = headA; } //长度的差值 int gap = abs(len1 - len2); //长的先走差值步 while (gap--) { LongList = LongList->next; } //同时走 while (LongList != ShortList) { LongList = LongList->next; ShortList = ShortList->next; } return LongList; }
算法复杂度: 时间:O(N),空间:O(1)
OJ链接
题目要求:
解析:
bool hasCycle(struct ListNode *head) {
struct ListNode* slow, *fast;
slow = fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//相遇即带环
if(fast == slow)
return true;
}
return false;
}
算法复杂度: 时间:O(N),空间:O(1)
拓展:
为什么满指针每次走一步,快指针每次走两步可以?
假设链表带环,那么最终慢指针和快指针都会进环。快指针先进环,慢指针后进环。最坏的情况是:慢指针刚进环时,快指针恰好在慢指针前面一步(环内),此时两者之间的距离是环的长度-1。慢指针走一步,快指针走两步,(可以根据相对运动的角度理解:慢指针不动,快指针走一步),每次两指针之间的距离都会-1,那么最终就一定会追上。
快指针每次走3步、4步、… … 、n步可以吗?
假定快指针每次走3步,环的长度为C。慢指针进环时,两指针之间的距离是X。每次循环(走)两指针之间的距离X减2。
- 如果进环时,环长C是偶数,两指针之间的距离X也是偶数,最终,会追上(fast==slow);
- 如果进环时,环长C是偶数,两指针之间的距离X是奇数,每次距离减2,最终,两指针会错过(fast ==slow->next),此时两指针之间的距离X是C-1(奇数),每次距离减2,就会永远错过,不会相遇(fast ==slow)。
OJ链接
题目要求:
解析:
法一(推荐):
meet=slow
(相遇结点位置),cur=head
(头结点)。两指针同时走,当两指针相遇(cur==meet
),相遇的结点即为入环的第一个结点。struct ListNode *detectCycle(struct ListNode *head) { struct ListNode* fast = head, *slow = head; while(fast && fast->next) { slow = slow->next; fast = fast->next->next; if(fast == slow) { struct ListNode* meet = slow; struct ListNode* cur = head; //一个指针从头走,同时另一个指针从相遇点走,两者会在入环的第一个结点相遇 while(meet != cur) { cur = cur->next; meet = meet->next; } return meet; } } return NULL; }
算法复杂度: 时间:O(N),空间:O(1)。
//求相交链表的第一个公共结点 struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) { if (!headA || !headB) return NULL; struct ListNode* cur1 = headA; struct ListNode* cur2 = headB; int len1 = 1; int len2 = 1; //找尾结点,并记录链表长度 while (cur1->next) { cur1 = cur1->next; len1++; } while (cur2->next) { cur2 = cur2->next; len2++; } //两链表不交叉 if (cur1 != cur2) { return NULL; } // struct ListNode* LongList = headA; struct ListNode* ShortList = headB; if (len1 < len2) { LongList = headB; ShortList = headA; } //长度的差值 int gap = abs(len1 - len2); //长的先走差值步 while (gap--) { LongList = LongList->next; } //同时走 while (LongList != ShortList) { LongList = LongList->next; ShortList = ShortList->next; } return LongList; } struct ListNode *detectCycle(struct ListNode *head) { struct ListNode* slow = head, *fast = head; while(fast && fast->next) { fast = fast->next->next; slow = slow->next; if(fast == slow) { struct ListNode* meet = slow; struct ListNode* next = meet->next; //将环断开,变成相交链表问题 meet->next = NULL; struct ListNode* entryNode = getIntersectionNode(head, next); meet->next = next; return entryNode; } } return NULL; }
算法复杂度: 时间:O(N),空间:O(1)
OJ链接
题目要求:
解析:
random->next
。struct Node* copyRandomList(struct Node* head) { struct Node* cur = head; struct Node* copy = NULL; struct Node* next = NULL; //复制 while(cur) { copy = (struct Node*)malloc(sizeof(struct Node)); assert(copy); copy->val = cur->val; next = cur->next; cur->next = copy; copy->next = next; //后移 cur = next; } //链接random指针 cur = head; while(cur) { copy = cur->next; if(cur->random == NULL) copy->random = NULL; else copy->random = cur->random->next; cur = cur->next->next; } //还原原链表 struct Node* copyhead = NULL, *copytail = NULL; cur = head; while(cur) { copy = cur->next; next = copy->next; //取copy结点 尾插 if(copytail == NULL) { copyhead = copytail = copy; } else { copytail->next = copy; copytail = copytail->next; } //恢复原链表 cur->next = next; cur = next; } return copyhead; }
算法复杂度: 时间:O(N),空间:O(1)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。