leetcode链表问题

链表相关问题总结

链表相关问题

链表问题一般通过维护多个节点的指针,在链表中穿针引线来进行解决。另外一个常用的技巧就是通过创建一个虚拟头结点(主要用于头结点可能被改变的场景之下),使之连接到节点中

//
// Created by yzm on 12/3/18.
//
#include <iostream>
using namespace std;

 struct ListNode {
      int val;
      ListNode *next;
      ListNode(int x) : val(x), next(NULL) {}
  };

//链表问题没有特殊说明,不能改变链表中的值
 /**
  * 206.翻转链表
  * */
class Solution1 {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *pre = nullptr;
        ListNode *next = nullptr;
        while ((head != nullptr)){
            next = head->next;
            head->next = pre;
            pre = head;
            head = next;
        }

        return pre;
    }
    //用类似第二提的方法左超 出时间限制
    ListNode* reverseList2(ListNode* head) {
        if(head == nullptr||head->next == nullptr)
            return head;
        ListNode dummy(-1);
        dummy.next = head;
        ListNode *pre = &dummy;
        pre = head->next;
        ListNode *cur = pre->next;
        while(cur->next != nullptr) {
            pre->next = cur->next;
            cur->next = head->next;
            head->next = cur;//头插法
            cur = pre->next;
        }

        return dummy.next;
    }
};

/**
  * 92.翻转链表2
  * 方法:穿针引线法
  * */

//此方法左时间太长
class Solution{
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode dummy(-1);
        dummy.next = head;
        ListNode *pre = &dummy;
        for(int i = 0; i < m-1; i++)
            pre = pre ->next;
        ListNode* const head2 = pre;
        pre = head2->next;
        ListNode *cur = pre->next;
        for(int i = m; i < n;i++) {
            pre->next = cur->next;
            cur->next = head2->next;
            head2->next = cur;//头插法
            cur = pre->next;
        }

        return dummy.next;
    }

};
/**
 * 83,删除排序表中重复元素,注意是有序的,就比较好办了
 * */
class Solution3 {
public:
    //递归版本实现,画出递归数
    ListNode* deleteDuplicates(ListNode* head) {
        if(head == nullptr)
            return head;
        ListNode dummy(head->val+1);
        dummy.next = head;
        recur(&dummy,head);
        return dummy.next;
    }
    void static recur(ListNode* pre,ListNode* cur){
        if(pre == nullptr)
            return;
        if(pre->val == cur->val ){
            pre->next = cur->next;
            delete cur;
            recur(pre,pre->next);
        } else{
            recur(pre->next,cur->next);
        }
    }
    //迭代版本,比递归版本要慢很多
    ListNode* deleteDuplicates2(ListNode* head) {

        ListNode* curNode = head;
        while (curNode != NULL&& curNode->next != NULL) {
            // 如果当前节点的val和下一节点的val相等,那么将当前节点链接到下下个节点,意思就是抛弃了相同的下一个节点
            if (curNode->val == curNode->next->val) {
                curNode->next = curNode->next->next;
            }
            else {	// 否则就是下一节点和当前节点不相同,那么curNode移位
                curNode = curNode->next;
            }
        }

        return head;
    }
};

/**
 * 86.分隔链表
 *给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
 * */
class Solution4 {
public:
    //我这种仅仅只是把相关的数进行
    ListNode* partition(ListNode* head, int x) {
        if(head == nullptr)
            return head;
        ListNode dummy(head->val-1);
        dummy.next = head;
        ListNode* pre = &dummy;
        ListNode *temp = nullptr;
        while (head != nullptr&&head->next != nullptr){
            if(head->val < x){
                pre = head;
                head = head ->next;
            } else{
                temp = head->next;
                pre ->next = head->next;
                head->next =temp->next;
                head = pre ->next;
            }


        }
        return dummy.next;
    }
    ListNode* partition2(ListNode* head, int x) {

        ListNode* res = new ListNode(0);
        res->next = head;
        ListNode* smallCurNode = res;
        ListNode* bigHead = new ListNode(0);
        ListNode* bigCurNode = bigHead;
        ListNode* curNode = head;
        while (curNode != NULL) {
            // 小于x,链接到小段
            if (curNode->val < x) {
                smallCurNode->next = new ListNode(curNode->val);
                smallCurNode = smallCurNode->next;
            }
            else {	// 不小于x,链接到大段
                bigCurNode->next = new ListNode(curNode->val);
                bigCurNode = bigCurNode->next;
            }
            curNode = curNode->next;
        }
        // 两个段链接起来
        smallCurNode->next = bigHead->next;

        return res->next;
    }


};
/**
 *328.奇偶链表
 * 思路: 和上一道题相似,但是要在原来的空间里的相应节点做后继指针的跳变,同理,还是记录好偶数的头结点,
 * 然后奇偶列表分别做各自的连接,待循环完成,将奇偶列表链接起来,维护好奇偶列表最后一个节点的额指针变量
 * */

class Solution5 {
public:
    ListNode* oddEvenList(ListNode* head) {

        if (head == NULL || head->next == NULL)
            return head;

        ListNode* oddTail = head;
        ListNode* evenTail = head->next;
        ListNode* evenHead = evenTail;
        while (evenTail != NULL && evenTail->next!=NULL) {
            // 偶数段后继节点为奇数,所以奇数段连接到此节点
            oddTail->next = evenTail->next;
            // 奇数段tail后移
            oddTail = oddTail->next;
            // 偶数段后继节点连接至下一个偶数节点
            evenTail->next = oddTail->next;
            // 偶数段tail后移
            evenTail = evenTail->next;
        }

        // 奇数段和偶数段连接
        oddTail->next = evenHead;
        return head;
    }
};
/**
 * 2.两数相加
 * */
class Solution6 {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* curL1 = l1;
        ListNode* curL2 = l2;

        ListNode* res = new ListNode(0);
        ListNode* head = res;

        int inHeight = 0;	// 进位
        while (curL1 != NULL || curL2 != NULL || inHeight != 0) {
            int numL1 = 0;		// l1当前位的值
            int numL2 = 0;		// l2当前位的值
            if (curL1 != NULL) {
                numL1 = curL1->val;
                curL1 = curL1->next;		// 循环变量维护
            }
            if (curL2 != NULL) {
                numL2 = curL2->val;
                curL2 = curL2->next;		// 循环变量维护
            }

            // 计算当前位的数字
            int numNow = numL1 + numL2 + inHeight;
            // 计算进位
            inHeight = numNow / 10;
            // 得到当前位的最终数字
            numNow = numNow % 10;

            // 循环变量维护
            res->next = new ListNode(numNow);
            res = res->next;
        }

        return head->next;
    }
};
/**
 * 203. 删除链表中的节点
 * */

class Solution7 {
public:
    ListNode* removeElements(ListNode* head, int val) {

        ListNode *dummmyHead = new ListNode(0);
        dummmyHead->next = head;
        ListNode *curNode = dummmyHead;

        while (curNode->next != NULL) {

            if (curNode->next->val == val) {
                ListNode *delNode = curNode->next;
                curNode->next = curNode->next->next;
                delete delNode;
            } else
                curNode = curNode->next;
        }
        return dummmyHead->next;
    }
};

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

class Solution8 {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {

        ListNode* dummmyHead = new ListNode(0);
        ListNode* curNode = dummmyHead;
        ListNode* curNodeL1 = l1;
        ListNode* curNodeL2 = l2;
        while (curNodeL1 != NULL || curNodeL2 != NULL) {
            // merge
            if (curNodeL1 == NULL) {
                curNode->next = new ListNode(curNodeL2->val);
                curNode = curNode->next;
                curNodeL2 = curNodeL2->next;
            }
            else if (curNodeL2 == NULL) {
                curNode->next = new ListNode(curNodeL1->val);
                curNode = curNode->next;
                curNodeL1 = curNodeL1->next;
            }
            else if (curNodeL1->val <= curNodeL2->val) {
                curNode->next = new ListNode(curNodeL1->val);
                curNode = curNode->next;
                curNodeL1 = curNodeL1->next;
            }
            else {
                curNode->next = new ListNode(curNodeL2->val);
                curNode = curNode->next;
                curNodeL2 = curNodeL2->next;
            }
        }

        return dummmyHead->next;
    }
};
/**
 * 24. 两两交换链表中的节点
 *给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
 * */
class Solution9 {
public:
    ListNode* swapPairs(ListNode* head) {

        ListNode* dummmyHead = new ListNode(0);
        dummmyHead->next = head;

        ListNode* pre = dummmyHead;
        // pre的后继两个节点都有值才需要翻转,不都有值那么不需要操作了
        while (pre->next && pre->next->next) {
            ListNode* node1 = pre->next;
            ListNode* node2 = node1->next;
            ListNode* next = node2->next;

            pre->next = node2;
            node2->next = node1;
            node1->next = next;

            pre = node1;
        }

        return dummmyHead->next;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值