数据结构链表例题(二)

--------------------------------------------例题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;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/c_living/article/details/80978165