赞
踩
- 删除链表中等于给定值 val 的所有节点。(OJ链接)
思想:双指针
- 首先我们维护一个prev和cur指针,prev先指向NULL,cur用于遍历链表
- prev用于保存cur的前一个节点,当cur->data等于val,然后自己定义一个next指针保存cur->next,这样就可以先free/delete节点,然后让prev->next指向next,之后把next给到cur就行了
- 时间复杂度O(n) 空间复杂度0(1)
当头不为空并且第一个节点的data就是val时,直接头节点指向下一个节点
struct ListNode* removeElements(struct ListNode* head, int val) { //当头不为空并且第一个节点就是val时,直接走到下一个节点 while(head && head->val == val) head = head->next; struct ListNode* prev = NULL; struct ListNode* cur = head; while(cur) { if(cur->val == val) { struct ListNode* next = cur->next; prev->next = next; free(cur); cur = next; } else { prev = cur; cur = cur->next; } } return head; }
- 反转一个链表。OJ链接
思想1:双指针
时间复杂度O(n) 空间复杂度0(1)
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;
}
思想2:取节点进行头插
时间复杂度O(n) 空间复杂度0(1)
class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* newnode = nullptr; ListNode* cur = head; while(cur) { ListNode* next = cur->next; //取节点进行头插 cur->next = newnode; newnode = cur; cur = next; } return newnode; } };
- 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个
中间结点。(OJ链接)
思想:快慢指针->一个指针走一步,另外一个指针走二步
时间复杂度:0(n) 空间复杂度0(1)
class Solution { public: ListNode* middleNode(ListNode* head) { if(head == NULL) return nullptr; ListNode* slow = head; ListNode* fast = head; //快慢指针 while(fast != NULL && fast->next != NULL) { slow = slow->next; fast = fast->next->next; } return slow; } };
- 输入一个链表,输出该链表中倒数第k个结点。(OJ链接)
思路:定义slow和fast指针,先让slow走k步,然后二个指针一起走,最后走到NULL,fast就是要找的倒数第k个节点
时间复杂度:0(n) 空间复杂度:0(1)
class Solution { public: ListNode* getKthFromEnd(ListNode* head, int k) { ListNode* slow = head; ListNode* fast = head; //向让slow走k步 while(k--) { //处理k大于链表有效数字情况 if(slow == NULL) return NULL; slow = slow->next; } //之后slow和fast一起走->slow为空则找到倒数第k个节点 while(slow != NULL) { slow = slow->next; fast = fast->next; } return fast; } };
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成
的。(OJ链接)
思想:带头单链表
时间复杂度:O(n) 空间复杂度0(1)
class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode* pHead = new ListNode(-1); ListNode* tail = pHead; while(list1 && list2) { if(list1->val < list2->val) { tail->next = list1; list1 = list1->next; } else { tail->next = list2; list2 = list2->next; } tail = tail->next; } tail->next = list1 == NULL ? list2 : list1; return pHead->next; } };
编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前。(OJ链接)
思想:开辟二个带哨兵位的单链表,判断原链表的每个数据,如果小于val则放到第一个链表中,反之放到另外一个链表中,然后将他们链接起来,返回哨兵位的下一个节点
class Solution { public: ListNode* partition(ListNode* head, int x) { ListNode* lessHead, *greaterHead, *lesstail, *greatertail; lessHead = lesstail = new ListNode(-1); greaterHead = greatertail = new ListNode(-1); lesstail->next = greatertail->next = NULL; ListNode* cur = head; while(cur != NULL) { if(cur->val < x) { lesstail->next = cur; lesstail = cur; } else { greatertail->next = cur; greatertail = cur; } cur = cur->next; } lesstail->next = greaterHead->next; greatertail->next = NULL; return lessHead->next; } };
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false.(OJ链接)
思路:找中间节点,反转中间节点之后的节点(包括中间节点),与中间节点之前的节点逐个判断是否相等,相等即为回文,不相等即不是回文。
class Solution { public: //反转链表成员函数 ListNode* reverse(ListNode* head) { ListNode* prev = NULL; ListNode* cur = head; while(cur != NULL) { ListNode* next = cur->next; cur->next = prev; prev = cur; cur = next; } return prev; } bool isPalindrome(ListNode* head) { //首先找链表中间节点 ListNode* slow = head; ListNode* fast = head; while(fast != NULL && fast->next !=NULL) { slow = slow->next; fast = fast->next->next; } //逆置(反转)中间节点后面的节点 slow = reverse(slow); //判断是否为回文 while(head && slow) { if(head->val == slow->val) { slow = slow->next; head = head->next; } else { return false; } } return true; } };
输入两个链表,找出它们的第一个公共结点。(OJ链接)
class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode* tailA = headA,*tailB = headB; int lenA = 1, lenB = 1; while(tailA->next) { tailA = tailA->next; ++lenA; } while(tailB->next) { tailB = tailB->next; ++lenB; } if(tailA != tailB) return NULL; //相交,求交点,长的先走差距步,在同时走找交点 ListNode* shortList = headA,*longList = headB; if(lenA > lenB) { longList = headA; shortList = headB; } int gap = abs( lenA-lenB); while(gap--) { longList = longList->next; } while(shortList && longList) { if(shortList == longList) return shortList; shortList = shortList->next; longList = longList->next; } return NULL; } };
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点,要求返回这个链表的深度拷贝。(OJ链接)
思路:在原链接每一个节点后面链接一个新开辟的节点,节点里面data与原链表节点的data相同,然后"顺藤摸瓜"把原链表的random->next给到新节点的random,最后剪断原链表和新节点之间的链接,让新开辟的节点成为新的链表,并且重新链接原来的链表。
class Solution { public: Node* copyRandomList(Node* head) { Node* cur = head; while(cur) { Node* copyNode = new Node(cur->val); copyNode->next = cur->next; cur->next = copyNode; cur = cur->next->next; } cur = head; while(cur) { if(cur->random == NULL) { cur->next->random = NULL; } else { cur->next->random = cur->random->next; } cur = cur->next->next; } cur = head; Node* copyHead = NULL; Node* copytail = NULL; while(cur) { Node* copy = cur->next; Node* next = copy->next; //原节点重新链接 cur->next = next; if(copyHead == NULL) { copyHead = copytail = copy; } else { copytail->next = copy; copytail = copytail->next; } cur = next; } return copyHead; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。