--------------------------------------------例题9----------------------------------------------
给定链表L
给定一个区间,要求逆置区间的数据。
Solution 1
利用插入排序的思想,吧需要逆置的区间视为一个逆序的数组需要进行插入排序。
public ListNode reverseBetween(ListNode head, int m, int n) {
if(head == null) return null;
ListNode dummy = new ListNode(0); // create a dummy node to mark the head of this list
dummy.next = head;
ListNode pre = dummy; // make a pointer pre as a marker for the node before reversing
for(int i = 0; i<m-1; i++) pre = pre.next;
ListNode start = pre.next; // a pointer to the beginning of a sub-list that will be reversed
ListNode then = start.next; // a pointer to a node that will be reversed
// 1 - 2 -3 - 4 - 5 ; m=2; n =4 ---> pre = 1, start = 2, then = 3
// dummy-> 1 -> 2 -> 3 -> 4 -> 5
for(int i=0; i<n-m; i++)
{
start.next = then.next;
then.next = pre.next;
pre.next = then;
then = start.next;
}
// first reversing : dummy->1 - 3 - 2 - 4 - 5; pre = 1, start = 2, then = 4
// second reversing: dummy->1 - 4 - 3 - 2 - 5; pre = 1, start = 2, then = 5 (finish)
return dummy.next;
}
-------------------------------
Solution 2:
利用额外的数组来记录数据(逆序记录)
然后覆盖原始数据
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {
int *temp = (int *)malloc(sizeof(int)*(n-m+1));
int TempCount = 0;
int PCount = 1;
PList p = (PList)malloc(sizeof(struct ListNode));
p = head;
while(PCount <= n)
{
if(PCount >= m)
{
temp[n-m-(TempCount)] = p->val;
TempCount++;
}
PCount++;
p = p->next;
}
p = head;
PCount =1;
TempCount = 0;
while(PCount <= n)
{
if(PCount >= m)
p->val = temp[TempCount++];
PCount++;
p = p->next;
}
return head;
}
-------------------------------------------------------------
Solution 3:
将区间的链表变成双向的链表
重新连接首尾
断开原来方向的指针
------------------------------------------------------例题10-------------------------------------------
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Solution 1:
申请一个辅助数组,在遍历链表的情况下同时将链表的每个地址记录进入数组。
在地址进入数组的时候需要比较数组中现有的地址
如果相同则该地址是循环开始点
struct ListNode *detectCycle(struct ListNode *head) {
PList sup[100000];
PList p = (PList)malloc(sizeof(struct ListNode));
p = head;
int count = 0;
while(p != NULL)
{
for(int i = 0;i < count;i++)
{
if(sup[i] == p)
return p;
}
sup[count++] = p;
p = p->next;
}
return NULL;
}
-----------------------------------
Solution 2:
设置一个快指针,每次步长为2,一个慢指针,步长为1.
记录两个指针第一次遇见的节点。
让快指针从头结点开始,步长变为1,慢指针从相遇节点开始,步长为1.
两个指针遇见的节点便是头结点。
1->2->3->4->->5->6--|
|_____________|
2k - k = N * r, r为圈长,并且N是1
设圈其实节点距离链表起始节点是X,并且在节点Y相遇,则:
节点Y距离圈起始节点的距离是m,
所以:X = k - m = r - m = 相遇节点到链表尾部的距离,有上面的相遇则为圈起始节点的理论。
struct ListNode *detectCycle(struct ListNode *head) {
PList Fast = (PList)malloc(sizeof(struct ListNode));
PList Slow = (PList)malloc(sizeof(struct ListNode));
PList Temp = (PList)malloc(sizeof(struct ListNode));
Fast = Slow = head;
int Count = 0;
while(Count < 2 && Fast != NULL)
{
if(Fast == Slow)
Count++;
if(Fast->next == NULL)
break;
if(Count < 2)
{
Fast = Fast->next->next;
Slow = Slow->next;
}
}
if(Count < 2)
return NULL;
else
{
Temp = Fast;
Fast = head;
while(Fast != Slow)
{
Fast = Fast->next;
Slow = Slow->next;
}
return Fast;
}
}
----------------------例题11---------------------------------------
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You may not modify the values in the list's nodes, only nodes itself may be changed.
Given 1->2->3->4, reorder it to 1->4->2->3.
Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
Solution 1:
将原来的链表L切割成两个链表,然后对第二个链表进行反转,这里采用递归的方法进行反转。
//递归反转链表
void reverseList(struct ListNode *head)
{
if(head->next == NULL)
return;
reverseList(head->next);
struct ListNode *temp = (struct ListNode *)malloc(sizeof(struct ListNode));
temp = head->next;
head->next = head->next->next;
temp->next = head;
}
//拼接
void reorderList(struct ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
int count = 0;
int length = 0;
int Mid;
struct ListNode *temp = head;
while(temp != NULL)
{
length++;
temp = temp->next;
}
Mid = (length-1)/2;
temp = head;
struct ListNode *A = head;
struct ListNode *B;
while(count < Mid)
{
count++;
temp = temp->next;
}
B = temp->next;
struct ListNode *RB = B;
while(RB->next != NULL)
RB = RB->next;
temp->next = NULL;
reverseList(B);
struct ListNode * NewHead = A;
struct ListNode * Last = NewHead;
A = A->next;
while(A != NULL)
{
struct ListNode *TA = (struct ListNode *)malloc(sizeof(struct ListNode));
TA->val = A->val;
TA->next = NULL;
struct ListNode *TB = (struct ListNode *)malloc(sizeof(struct ListNode));
TB->val = RB->val;
TB->next = NULL;
Last->next = TB;
Last->next->next = TA;
A = A->next;
RB = RB->next;
Last = Last->next->next;
}
if(RB != NULL)
Last->next = RB;
head = NewHead;
}
Solution 2:
利用栈来达到链表反转的效果:
class Solution {
public:
void reorderList(ListNode* head) {
if (!head) return;
stack<ListNode*> st;
ListNode* slow = head;
ListNode* fast = head;
while (fast && fast->next) { /* 反转后的尾节点 */
slow = slow->next;
fast = fast->next->next;
}
fast = slow;
while (slow = slow->next) /* 反转链表序列 */
st.push(slow);
fast->next = nullptr;
slow = head;
while (!st.empty()) { /* 序列拼接 */
fast = st.top();
st.pop();
fast->next = slow->next;
slow->next = fast;
slow = fast->next;
}
}
};
---------------------------------------------------例题12----------------------------------------
删除链表L上的节点,节点的值唯一,并且给出的是需要删除的节点的地址,不给链表。
Solution:
直接从需要删除的节点开始把数据往前面转移即可
void deleteNode(struct ListNode* node) {
struct ListNode * temp = node;
while(true)
{
if(temp->next->next == NULL)
{
temp->val = temp->next->val;
temp->next = NULL;
return;
}
else if(temp->next->next != NULL)
{
temp->val = temp->next->val;
temp = temp->next;
}
}
}