c++ 数据结构——链表

1.链表概念:

暂略。

2.栈的相关题目:

2.1 leetcode 237 —— Delete Node in a Linked List

注意:这个题没有给head~

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
    }
};

 2.2 ***leetcode 206 —— Reverse Linked List

这个题虽然简单但是还蛮重要的~

1.迭代:

参考链接:http://www.pianshen.com/article/517476376/

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = NULL;
        ListNode* nxt;
        while(head != NULL)
        {
            nxt = head->next;
            head->next = pre;
            pre = head;
            head = nxt;            
        }
        return pre;
    }
};

2.递归:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* res;
        
        if(head == NULL || head->next == NULL)
        {
            return head;
        }   
        
        res = reverseList(head->next);//保存最后一个节点 也是反转后的头节点
        head->next->next = head;
        head->next = NULL;
        return res;
    }
    
};

2.3 ***leetcode 21 —— Reverse Linked List

迭代:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* begin = NULL;
        ListNode* pre;
        if(!l1)
        {
            return l2;
        }
        if(!l2)
        {
            return l1;
        }
        while(l1 && l2)
        {
            if(l1->val <= l2->val)
            {
                if(!begin)
                {
                    begin = l1;
                }
                else    
                {
                    pre->next = l1;                    
                }
                pre = l1;
                l1 = l1->next;
            }
            else
            {
                if(!begin)
                {
                    begin = l2;
                }
                else 
                {
                    pre->next = l2;
                }
                pre = l2;
                l2 = l2->next;
            }
        }        
        pre->next = l1 ? l1 : l2;
        return begin;                
    }
};

递归:

做递归题的时候需要思考子问题是什么

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        //返回值永远是当前两个节点较小的那个
        if(l1 == NULL)
        {
            return l2;
        }
        else if(l2 == NULL)
        {
            return l1;
        }
        else
        {
            if(l1->val <= l2->val)
            {
                l1->next = mergeTwoLists(l1->next,l2);
                return l1;
            }
            else
            {
                l2->next = mergeTwoLists(l1,l2->next);
                return l2;
            }            
        }        
    }
};

2.4 ***leetcode 160 —— Intersection of Two Linked Lists

设A链长m,B链长n,相交点为长链中第k个。

容易想到的方法1:O(m+n+k)

思路:先计算两个链的长度,然后移动长链头结点到与短链相等处,然后开始判断两个链的当前节点是否相等

/**
 * 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) {
        if(headA == NULL || headB == NULL)
        {
            return NULL;
        }
        ListNode* A = headA;
        ListNode* B = headB;
        int lenA = 0;
        int lenB = 0;
        int i;
        while(A)
        {
            A = A->next;
            lenA++;
        }
        while(B)
        {
            B = B->next;
            lenB++;
        }
        i = lenA > lenB ? lenA - lenB : lenB - lenA;
        A = headA;
        B = headB;    
        if(lenA > lenB)
        {
            for(;i>0;i--)
            {
                A = A->next;
            }
        }
        else
        {
            for(;i>0;i--)
            {
                B = B->next;
            }
        }
        
        while(A != NULL || B != NULL)
        {            
            if(A == B)
            {
                return A;
            }
            else
            {
                A = A->next;
                B = B->next;
            }
        }
        return NULL;
    }
};

代码简洁的方法2:O(m+n)

把AB两个链拼接在一起,A的头结点走链A+B,B的头结点走链B+A,走的过程中判断两个链当前节点是否相等,拼接链的结尾为NULL,若没有交点走到最后两个链的当前节点也会都等于NULL。

/**
 * 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 *A = headA;
        ListNode *B = headB;
        while(A != B)
        {
            A = A ? A->next : headB;
            B = B ? B->next : headA;
        }
        return A;        
    }
};

2.5 ***leetcode 141 —— Linked List Cycle

快慢指针就可以解了~

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while(slow && fast && fast->next && fast->next != slow)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        if(!slow || !fast || !fast->next)
        {
            return false;
        }
        return true;
    }
};

2.6 ***leetcode 234 —— Palindrome Linked List

注意链表可以是偶数长度也可以是奇数长度。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(!head || !head->next)
        {
            return true;
        }
        if(!head->next->next)
        {
            if(head->val == head->next->val)
            {
                return true;
            }
            return false;
        }
        ListNode* middle = NULL;
        ListNode* begin = head;
        while(begin && begin->next && begin->next->next)
        {
            if(begin->val == begin->next->next->val)
            {
                middle = begin->next->next;
                begin->next = NULL;
                break;
            }
            else if(begin->val == begin->next->val)
            {
                middle = begin->next;
                begin->next = NULL;
                break;
            }
            else
            {
                begin = begin->next;
            }
        }
        if(!middle)
        {
            return false;
        }
        else
        {
            ListNode* pre = NULL;
            ListNode* nxt;
            while(middle)
            {                
                nxt = middle->next;
                middle->next = pre;
                pre = middle;
                middle = nxt;
            }
            while(head && pre)
            {
                if(head->val != pre->val)
                {
                    return false;
                }
                else
                {
                    head = head->next;
                    pre = pre->next;
                }
            }
            if(!head && !pre)
            {
                return true;
            }
            
        }
        return false;
    }
};

2.7 ***leetcode 148 —— Sort List

这个题用的是归并排序,各个排序的复杂度对比见此链接:

但是用链表实现起来比较困难,我参考了下面的链接:(链接内容非常好!

https://leetcode-cn.com/problems/sort-list/solution/148-pai-xu-lian-biao-bottom-to-up-o1-kong-jian-by-/

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        ListNode begin(0);
        begin.next = head;
        auto p = head;
        int len = 0;
        while(p)
        {
            len++;
            p = p->next;
        }
        for(int step = 1;step < len;step <<= 1)
        {
            auto cur = begin.next;
            auto tail = &begin;
            while(cur)
            {
                auto left = cur;
                auto right = cut(left,step);
                cur = cut(right,step);
                tail->next = merge(left, right);
                while (tail->next) 
                {
                    tail = tail->next;
                }
            }            
        }
        return begin.next;
    }
    ListNode* cut(ListNode* head,int n)
    {
        auto p = head;
        while(--n && p)
        {
            p = p->next;
        }
        if(!p) return p;
        auto nxt = p->next;
        p->next = NULL;
        return nxt;
    }
    ListNode* merge(ListNode* l1,ListNode* l2)
    {
        ListNode* begin = NULL;
        ListNode* pre;
        if(!l1)
        {
            return l2;
        }
        if(!l2)
        {
            return l1;
        }
        while(l1 && l2)
        {
            if(l1->val <= l2->val)
            {
                if(!begin)
                {
                    begin = l1;
                }
                else    
                {
                    pre->next = l1;                    
                }
                pre = l1;
                l1 = l1->next;
            }
            else
            {
                if(!begin)
                {
                    begin = l2;
                }
                else 
                {
                    pre->next = l2;
                }
                pre = l2;
                l2 = l2->next;
            }
        }
        pre->next = l1 ? l1 : l2;
        return begin;
        
    }
};

2.8 ***leetcode 328 —— Odd Even Linked List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if(!head)
        {
            return NULL;
        }
        if(!head->next || !head->next->next)
        {
            return head;
        }
        ListNode evenBegin(0);
        ListNode* odd = head;
        ListNode* even = head->next;
        evenBegin.next = even;
        
        while(even && even->next)
        {
            odd->next = even->next;
            odd = odd->next;
            even->next = odd->next;
            even = even->next;
        }
        odd->next = evenBegin.next;
        return head;
    }
};

2.9 ***leetcode 2 —— Add Two Numbers

链表后元素置0使两个链表长度相等

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode dummyHead(0);
        ListNode* curr = &dummyHead;
        int carry = 0;
        while(l1 || l2)
        {
            int a = l1? l1->val : 0;
            int b = l2? l2->val : 0;
            int sum = a + b + carry;
            curr->next = new ListNode(sum % 10);
            curr = curr->next;            
            carry = sum / 10;
            l1 = l1 ? l1->next : l1;
            l2 = l2 ? l2->next : l2;
        }
        if(carry)
        {            
            curr->next = new ListNode(carry);
        }
        return dummyHead.next;
    }
};

2.10 ***leetcode 19 —— Remove Nth Node From End of List

用快慢指针做

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* fast = head;
        ListNode* slow = head;
        ListNode dummyHead(0);
        dummyHead.next = head;
        ListNode* pre = &dummyHead;
        while(n--)
        {
            fast = fast->next;
        }
        while(fast)
        {
            fast = fast->next;
            pre = slow;
            slow = slow->next;
        }
        pre->next = slow->next;
        return dummyHead.next;
    }
};

2.11 ***leetcode 142 —— Linked List Cycle II

题解参考:https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode/

/**
 * 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* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
            {
                break;
            }
        }
        if(!fast || !fast->next)
        {
            return NULL;
        }
        slow = head;
        while(slow != fast)
        {
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }
};

2.12 ***leetcode 138 —— Copy List with Random Pointer

这个问题的关键在于找拷贝后结点的random位置,比较笨的办法是,先不管random按照next建立深拷贝后的链表,然后再从第一个结点开始,遍历新链表,并将random赋值。这个方法的复杂度为O(n∧2)。

所以问题的核心就是想办法在O(n)时间内找到每个新节点random该指的位置。

因此参考此链接的方法3:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/fu-zhi-dai-sui-ji-zhi-zhen-de-lian-biao-by-leetcod/

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;

    Node() {}

    Node(int _val, Node* _next, Node* _random) {
        val = _val;
        next = _next;
        random = _random;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(!head)
        {
            return NULL;
        }
        Node dummyHeadOld(0,NULL,NULL);
        dummyHeadOld.next = head;
        while(head)
        {
            Node* tmp = new Node(head->val,head->next,NULL);
            head->next = tmp;
            head = tmp->next;
        }
        Node dummyHeadNew(0,NULL,NULL);
        dummyHeadNew.next = dummyHeadOld.next->next;
        Node* p = dummyHeadNew.next;
        head = dummyHeadOld.next;        
        while(head)
        {
            p->random = head->random ? head->random->next : NULL;
            head = p->next;
            if(head)
            {
                p = head->next;  
            }          
        }
        head = dummyHeadOld.next;
        p = dummyHeadNew.next;
        while(head)
        {
            head->next = p->next;
            head = head->next;
            if(head)
            {
                p->next = head->next;
                p = p->next;
            }
        }
        return dummyHeadNew.next;
    }
};

2.13 ***leetcode 61 —— Rotate List

注意k比链表长的情况

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head)
        {
            return NULL;
        }
        if(!k || !head->next)
        {
            return head;
        }
        ListNode dummyHead(0);
        dummyHead.next = head;
        ListNode* tail;
        int len = 0;
        int newK = 0;
        while(head)
        {
            if(!head->next)
            {
                tail = head;
            }
            head = head->next;
            len++;
        }
        newK = len - (k % len) + 1;
        head = dummyHead.next;
        for(int i = 1;i < newK -1;i++)
        {
            head = head->next;
        }
        tail->next = dummyHead.next;
        dummyHead.next = head->next;
        head->next = NULL;
        return dummyHead.next;
    }
};

2.14 ***leetcode 23 —— Merge k Sorted Lists

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size() < 1)
        {
            return NULL;
        }
        for(int step = 1;step < lists.size();step = step * 2)
        {
            int curr = 0;
            while(curr < lists.size())
            {
                lists[curr] = (curr + step) < lists.size() ? merge(lists[curr],lists[curr+step]) : lists[curr];
                curr += 2 * step;
            }
        }
        return lists[0];
    }
    
    ListNode* merge(ListNode* l1,ListNode* l2)
    {
        ListNode* begin = NULL;
        ListNode* pre;
        if(!l1)
        {
            return l2;
        }
        if(!l2)
        {
            return l1;
        }
        while(l1 && l2)
        {
            if(l1->val <= l2->val)
            {
                if(!begin)
                {
                    begin = l1;
                }
                else
                {
                    pre->next = l1;
                }
                pre = l1;
                l1 = l1->next;
            }
            else
            {
                if(!begin)
                {
                    begin = l2;
                }
                else
                {
                    pre->next = l2;
                }
                pre = l2;
                l2 = l2->next;
            }
        }
        pre->next = !l1 ? l2 : l1;
        return begin;
    }
};

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表的反转可以通过修改节点的前驱和后继指针来实现。以下是一个示例代码实现: ```c #include <stdio.h> #include <stdlib.h> // 定义双链表节点 struct Node { int data; struct Node* prev; struct Node* next; }; // 反转双链表 struct Node* reverse(struct Node* head) { struct Node* current = head; struct Node* temp = NULL; while (current != NULL) { // 交换当前节点的前驱和后继指针 temp = current->prev; current->prev = current->next; current->next = temp; // 向后移动 current = current->prev; } // 更新头节点指针 if (temp != NULL) { head = temp->prev; } return head; } // 打印双链表 void printList(struct Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } } int main() { // 创建双链表 struct Node* head = (struct Node*)malloc(sizeof(struct Node)); struct Node* second = (struct Node*)malloc(sizeof(struct Node)); struct Node* third = (struct Node*)malloc(sizeof(struct Node)); head->data = 1; head->prev = NULL; head->next = second; second->data = 2; second->prev = head; second->next = third; third->data = 3; third->prev = second; third->next = NULL; printf("原始双链表:"); printList(head); // 反转双链表 head = reverse(head); printf("\n反转后的双链表:"); printList(head); return 0; } ``` 这段代码首先定义了一个 `Node` 结构体来表示双链表的节点,其中包括一个数据域 `data`、一个指向前驱节点的指针 `prev`,以及一个指向后继节点的指针 `next`。 在 `reverse` 函数中,我们使用一个临时变量 `temp` 来交换当前节点的前驱和后继指针,然后将当前节点指针向后移动。反转完成后,更新头节点指针,确保它指向反转后的链表的头部。 最后,在 `main` 函数中创建一个简单的双链表,并调用 `reverse` 函数进行反转操作。通过调用 `printList` 函数来打印原始链表和反转后的链表。 以上代码的输出结果应为: ``` 原始双链表:1 2 3 反转后的双链表:3 2 1 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值