数据结构与算法——链表题目实现

文章目录

        • 1.链表逆序
          • 1.1 题目描述
          • 1.2链表逆序的C++实现
        • 2.反转链表
          • 2.1 题目描述
          • 2.2 反转链表的C++实现
        • 3.求两个链表的交点
          • 3.1 题目描述
          • 3.2 C++实现——set
          • 3.3 C语言实现——链表长度实现
        • 4.链表求环
          • 4.1 题目描述
          • 4.2 C++实现
          • 4.3 C语言实现——快慢指针
        • 5.分隔链表
          • 5.1 题目描述
          • 5.2 C++实现
        • 6.复制带随机指针的链表
            • 6.1 题目描述
            • 6.2 C++实现
        • 7.排序链表的合并
          • 7.1 题目描述
          • 7.2 C++实现
        • 8.多个排序链表的合并
          • 8.1 题目描述
          • 8.2 C++实现
          • 8.3 C++实现——分治

1.链表逆序
1.1 题目描述

反转一个单链表。
示例:
\qquad 输入: 1->2->3->4->5->NULL
\qquad 输出: 5->4->3->2->1->NULL

1.2链表逆序的C++实现
#include
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x):val(x),next(NULL){}
};
class Solution {
public:
    ListNode* reverseList(ListNode* head) 
    {
        ListNode* new_head = NULL;
        while (head) {
            ListNode* next;
            next = head->next;
            head->next = new_head;
            new_head = head;
            head = next;
        }
        return new_head;
    }
};
2.反转链表
2.1 题目描述

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

2.2 反转链表的C++实现
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x):val(x),next(NULL){}
};
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        int change_len = right-left+1;
        ListNode *pre_head=NULL;
        ListNode *result=head;
        while(head&&--left){
            pre_head=head;
            head=head->next;
        }

        ListNode *modify_list_tail=head;
        ListNode *new_head=NULL;
        while(head&&change_len){
            ListNode *next=head->next;
            head->next=new_head;
            new_head=head;
            head=next;
            change_len--;
        }
        modify_list_tail->next=head;
        if(pre_head){
            pre_head->next=new_head;
        }
        else{
            result=new_head;
        }
        return result;
    }
};
3.求两个链表的交点
3.1 题目描述

编写一个程序,找到两个单链表相交的起始节点。

3.2 C++实现——set
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x):val(x),next(NULL){}
};
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        set<ListNode*> Node_set;
        while(headA){
            Node_set.insert(headA);
            headA=headA->next;
        }
        while(headB){
            if(Node_set.find(headB)!=Node_set.end()){
                return headB;
            }
            headB=headB->next;
        }
        return NULL;
    }
};
3.3 C语言实现——链表长度实现

步骤1:计算headA和headB的长度
步骤2:将较长链表的指针移动到和较短链表指针对齐的地方
步骤3:两个链表同时移动,当两者指向同一个结点时,结点被找到

int get_list_legth(struct ListNode *head){
     int len=0;
     while(head){
         len++;
         head=head->next;
     }
     return len;
 }

 struct ListNode *forward_long_list(int long_len,int short_len,struct ListNode *head){
     int delta=long_len-short_len;
     while(head&&delta){
         head=head->next;
         delta--;
     }
     return head;
 }
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    int list_A_len=get_list_legth(headA);
    int list_B_len=get_list_legth(headB);

    if(list_A_len>list_B_len){
        headA=forward_long_list(list_A_len,list_B_len,headA);
    }
    if(list_B_len>list_A_len){
        headB=forward_long_list(list_B_len,list_A_len,headB);
    }
    while(headA&&headB){
        if(headA==headB){
            return headA;
        }
        headA=headA->next;
        headB=headB->next;
    }
    return NULL;
}
4.链表求环
4.1 题目描述

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

4.2 C++实现
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        set<ListNode *> node_list;
        while(head){
            if(node_list.find(head)!=node_list.end()){
                return head;
            }
            node_list.insert(head);
            head=head->next;
        }
        return NULL;
        }
};
4.3 C语言实现——快慢指针
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast=head;
    struct ListNode *slow=head;

    while(fast!=NULL){
        slow=slow->next;
        if(fast->next==NULL){
            return NULL;
        }
        fast=fast->next->next;
        if(fast==slow){
            struct ListNode *ptr=head;
            while(ptr){
                if(ptr==slow){
                    return ptr;
                }
                ptr=ptr->next;
                slow=slow->next;
            }   
        }
    }
    return NULL;
}
5.分隔链表
5.1 题目描述

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

5.2 C++实现
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode less_head(0);
        ListNode more_head(0);
        ListNode *less_ptr=&less_head;
        ListNode *more_ptr=&more_head;

        while(head){
            if(head->val<x){
                less_ptr->next=head;
                less_ptr=head;
            }
            else{
                more_ptr->next=head;
                more_ptr=head;
            }
            head=head->next;
        }
        less_ptr->next=more_head.next;
        more_ptr->next=NULL;
        return less_head.next;

    }
};
6.复制带随机指针的链表
6.1 题目描述

题目描述

6.2 C++实现
#include
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x):val(x),next(NULL){}
};
class Solution {
public:
    Node* copyRandomList(Node* head) {
        map<Node *,int>  node_map;
        vector<Node *> node_vec;
        Node *ptr=head;
        int i=0;
        while(ptr){
            node_map[ptr]=i;
            node_vec.push_back(new Node(ptr->val));
            ptr=ptr->next;
            i++;
        }
        node_vec.push_back(0);
        ptr=head;
        i=0;
        while(ptr){
            node_vec[i]->next=node_vec[i+1];
            if(ptr->random){
                int id=node_map[ptr->random];
                node_vec[i]->random=node_vec[id];
            }
            ptr=ptr->next;
            i++;
        }
        return node_vec[0];
    }
};
7.排序链表的合并
7.1 题目描述

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

7.2 C++实现
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode temp_head(0);
        ListNode *pre=&temp_head;

        while(l1&&l2){
            if(l1->val<l2->val){
                pre->next=l1;
                l1=l1->next;
            }
            else{
                pre->next=l2;
                l2=l2->next;
            }
            pre=pre->next;
        }
        if(l1){
            pre->next=l1;
        }
        if(l2){
            pre->next=l2;
        }
        return temp_head.next;
    }
};
8.多个排序链表的合并
8.1 题目描述

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

8.2 C++实现
bool cmp(ListNode *a,ListNode *b){
     return a->val<b->val;
 }
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        vector<ListNode *> node_vec;
        int i;
        for(i=0;i<lists.size();i++){
            ListNode *head=lists[i];
            while(head){
                node_vec.push_back(head);
                head=head->next;
            }
        }
        if(node_vec.size()==0){
            return NULL;
        }
        sort(node_vec.begin(),node_vec.end(),cmp);
        for(i=1;i<node_vec.size();i++){
            node_vec[i-1]->next=node_vec[i];
        }
        node_vec[node_vec.size()-1]->next=NULL;
        return node_vec[0];
    }
};
8.3 C++实现——分治
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode temp_head(0);
        ListNode *pre=&temp_head;

        while(l1&&l2){
            if(l1->val<l2->val){
                pre->next=l1;
                l1=l1->next;
            }
            else{
                pre->next=l2;
                l2=l2->next;
            }
            pre=pre->next;
        }
        if(l1){
            pre->next=l1;
        }
        if(l2){
            pre->next=l2;
        }
        return temp_head.next;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size()==0){
            return NULL;
        }
        if(lists.size()==1){
            return lists[0];
        }
        if(lists.size()==2){
            return mergeTwoLists(lists[0],lists[1]);
        }
        int mid=lists.size()/2;
        vector<ListNode *> sub1_lists;
        vector<ListNode *> sub2_lists;
        int i;
        for(i=0;i<mid;i++){
            sub1_lists.push_back(lists[i]);
        }
        for(i=mid;i<lists.size();i++){
            sub2_lists.push_back(lists[i]);
        }

        ListNode *l1=mergeKLists(sub1_lists);
        ListNode *l2=mergeKLists(sub2_lists);
        return mergeTwoLists(l1,l2);
    }
};

你可能感兴趣的:(数据结构,链表,指针,算法,数据结构)