赞
踩
// 单链表 struct ListNode { int val; // 节点上存储的元素 ListNode *next; // 指向下一个节点的指针 ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数 };
定义一个节点
ListNode* head = new ListNode(5);
作用:设置虚拟头结点使对头结点的处理普遍化
ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点 dummyHead->next = head; // 将虚拟头结点指向head,使后续对头结点操作普遍化 ListNode* cur = dummyHead;
题目
给你单链表的头指针 head
和两个整数left
和right
,其中left <= right
。请你反转从位置 left 到位置right
的链表节点,返回 反转后的链表 。
来源:力扣(LeetCode) 链接:力扣
思路
设置虚拟头结点,使对第一个节点考虑具有一般性;
找到left
前面一个元素位置,利用头插法将left
与right
之间元素插入到left
后面。
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* reverseBetween(ListNode* head, int left, int right) { ListNode* virtualhead; virtualhead = new ListNode(0); virtualhead ->next = head; ListNode* cur = virtualhead; while(--left){ cur = cur->next; right--; } head = cur; //使head指向left左面一个元素 cur = head->next; while(--right){ //头插法 ListNode* temp = cur->next; cur->next = temp->next; temp->next = head->next; head->next = temp; } return virtualhead->next; } };
题目
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
来源:力扣(LeetCode) 链接:力扣
思路
设置虚拟头结点,使对第一个节点考虑具有一般性;
利用快慢指针,初始时快慢指针均指向链表虚拟头结点,快指针先走N
步,之后快慢指针一同移动,直至快指针指向空指针,慢指针指向元素即为要删除元素前一个元素,删除即可。
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode* virtualhead = new ListNode(0); virtualhead ->next = head; ListNode* cur = virtualhead; ListNode* cur1 = virtualhead; while(cur->next && n--){ cur = cur->next; } while(cur->next){ cur = cur->next; cur1 = cur1->next; } cur1->next = cur1->next->next; return virtualhead->next; } };
题目
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
来源:力扣(LeetCode) 链接:力扣
思路
设置两个指针p1
、p2
分别指向A、B两个单链表的起始节点;
假设两个指针p1
与p2
分别从开始位置移动到链表的结束位置,则两个指针走过长度差值就为两链表起始节点到相交节点长度间的差值;
若两个指针从出发点移动,到达终点后,继续从对方出发点出发,则当二者相遇时节点就为链表相交点,因为到达该点时二者走过相同的路径,正好相遇。
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode *h1 = headA, *h2 = headB; while(h1!=h2){ h1 = h1 == nullptr? headB: h1->next; h2 = h2 == nullptr? headA: h2->next; } return h1; } };
题目
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果pos
是 -1,则在该链表中没有环。注意,pos
仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:
你是否可以使用 O(1) 空间解决此题?
来源:力扣(LeetCode) 链接:力扣
思路
设置两个快慢指针fast
、slow
,fast
指针一次走两步,slow
指针一次走一步;
两个指针从出发点开始出发至两者相遇,slow
指针立即返回至出发点重新出发,fast则改为一次行走一步继续前进,则当两者相遇时节点就为环形入口;
首先明确一点,当fast
指针与slow
指针相遇时,slow指针一定正在走环形路径的第一圈,为得到这样的结论,可以假设最边界情况,即当slow指针刚进入环形时,fast
正好在其前面一个,在这种情况下,slow
走一圈,fast
走两圈,两个指针在环形入口前附近相遇,则此时slow
指针一定正在走环形路径的第一圈;
两个指针从出发点开始至两者相遇,走过相同的路径为x+y
,由于fast指针速度是slow
指针2倍,fast
指针走过路程为slow
指针走过路程2倍,当两个指针相遇时,fast
指针比slow
指针多走若干圈(整数),并且多走的圈的总长度就为slow所走过路程长度;
当两个指针第一次相遇时,fast
指针以一次一步速度继续前进,slow
指针从出发点重新出发,由于slow
指针从出发点到达第一次相遇点路程长度与fast
多走的圈(整数个)路程长度相同,则两个指针可同时到达第一次相遇点,但在到达第一次相遇节点前,两者实际已经相伴走过y路程,两者同时回退y步即为第二次相遇点,也就是环形路径入口点。
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *slow=head, *fast=head; while(fast&&fast->next){ slow = slow->next; fast = fast->next->next; if(slow == fast){ slow = head; while(slow!=fast){ slow = slow->next; fast = fast->next; } return slow; } } return nullptr; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。