OJ_链表

1.环形链表1:(1~3)

给定一个链表,判断链表中是否有环。

/**
 * 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* fast=head;
        ListNode* slow=head;
        while(fast && fast->next){
            fast=fast->next->next;   //快指针一次走两步
            slow=slow->next;  //慢指针一次走一步
            if(fast==slow)   //如果有环一定会相遇
                return true;
        }
        return false;
    }
};

2.环形链表2:公式法

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
OJ_链表_第1张图片

/**
 * 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){  //相遇后,确定入环结点
                ListNode* meet=slow;
                ListNode* cur=head;
                //找到入环结点:如图所示,因为 L=C-X,所以meet和cur会走相同的距离,一定会在入环点相遇
                while(meet!=cur){  
                    cur=cur->next;
                    meet=meet->next;
                }
                return cur;
            }
        }
        return nullptr;
    }
};

3.相交链表:

编写一个程序,找到两个单链表相交的起始节点。如果两个链表没有交点,返回 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* curA=headA;
        ListNode* curB=headB;
        int lenA=0,lenB=0;
        if(headA==nullptr || headB==nullptr)
            return nullptr;
        while(curA && curA->next){
            ++lenA;
            curA=curA->next;
        }
        while(curB && curB->next){
            ++lenB;
            curB=curB->next;
        }
        if(curA!=curB)
            return nullptr;
        else{
            ListNode* longlist=headA;  //找到长的链表
            ListNode* shortlist=headB;
            if(lenA<lenB){
                longlist=headB;
                shortlist=headA;
            }
            int gap=abs(lenA-lenB);
            while(gap--)    //长的链表先走gap步
                longlist=longlist->next;
            while(longlist!=shortlist){   //然后一起走,直到相遇
                longlist=longlist->next;
                shortlist=shortlist->next;
            }
            return longlist;
        }
    }
};

4.链表的中间结点:(4~5)

给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        //双指针
        ListNode* fast=head;
        ListNode* slow=head;
        while(fast && fast->next){
            fast=fast->next->next;
            slow=slow->next;
        }
        return slow;
    }
};

5.删除链表的倒数第N个结点:

给你一个链表,删除链表的倒数第 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) {
        //双指针,让fast先走n步,然后一起走,直到走到末尾
        //最后slow指向的是倒数第n个结点的**前一个结点**
        //如果fast先走n-1步,然后一起走,则最后slow指向的是倒数第n个结点
        ListNode* fast=head;
        ListNode* slow=head;
        ListNode* tmp=nullptr;
        if(head==nullptr)    //如果链表为空则返回
            return nullptr;
        while(n--)   //快指针先走n步
            fast=fast->next;
        while(fast && fast->next){   //然后一起走
            slow=slow->next;
            fast=fast->next;
        }

        if(fast==nullptr){  //如果删除的是第一个结点
            tmp=head;
            head=head->next;
            delete tmp;
        }
        else{  //如果删除的是其余结点
            tmp=slow->next;
            slow->next=tmp->next;
            delete tmp;
        }
        return head;
    }
};

6.反转链表:

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

/**
 * 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* cur=head;
        ListNode* pre=nullptr;
        head=nullptr;
        while(cur!=nullptr){
            pre=cur;
            cur=cur->next;
            pre->next=head;
            head=pre;
        }
        return head;
    }
};

7.合并两个有序链表:

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

/**
 * 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* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* dummy=new ListNode(-1);  //创建一个头结点
        ListNode* pre=dummy;
        while(l1 && l2){   //l1和l2都不为空时
            if(l1->val<l2->val){  
                pre->next=l1;
                l1=l1->next;
            }
            else{
                pre->next=l2;
                l2=l2->next;
            }
            pre=pre->next;
        }
        //合并后 l1 和 l2 最多只有一个还未被合并完,直接将链表末尾指向未合并完的链表即可
        pre->next=(l1==nullptr ? l2 : l1);
        return dummy->next;
    }
};

8.移除链表元素:

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

/**
 * 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* removeElements(ListNode* head, int val) {
        //双指针
        ListNode* cur=head;  //指向当前结点
        ListNode* pre=nullptr;  //指向当前结点的前驱
        if(head==nullptr)   //处理第一个结点,若为空
            return nullptr;
            
        while(cur!=nullptr){   //遍历
            if(head->val==val){ //处理第一个结点,若第一个结点要删除
                head=cur->next;
                delete cur;
                cur=head;
            }
            else if(cur->val==val){  //删除
                pre->next=cur->next;
                delete cur;
                cur=pre->next;
            }
            else{   //后移
                pre=cur;
                cur=cur->next;
            }
        }
        return head;
    }
};

你可能感兴趣的:(OJ,c++)