leetcode24. 两两交换链表中的节点(三种解答方法)

方法一:递归


思路与算法
递归常用来解答链表和二叉树中的题目,在用递归时,牢记一点:递归的本质是反复调用自身,不要过度关系递归每一层的实现,只需要明白一级递归的过程即可。 写递归的套路(只需明白的三个地方): 1、递归什么时候结束? 2、递归的返回值是什么? 3、本级递归的目的是什么?(本级递归的操作是什么?) 本题中,题目要求我们两两交换链表中的节点,我们按照套路思考: 1、递归什么时候结束: 在只剩下一个节点或者没有节点的时候结束递归,因为只有一个节点时和没有节点时不需要再进行操作。 2、递归的返回值是什么? 可以将当前递归看作为三个节点的操作,使当前头节点指向第三个节点,第二个节点指向头节点,需要注意的时:第三个节点是需要继续递归的链表,他的头节点是第二个节点。如图所示:

leetcode24. 两两交换链表中的节点(三种解答方法)_第1张图片

 递归的主体部分就是交换三个节点的前两个而已。


/**
 * 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* swapPairs(ListNode* head) {
        //递归牢记:不用管函数每一层做了是什么,只要知道第一层做了什么就行!
        //解题套路:1、找结束时的条件2、找递归返回值3、找当前这层执行什么
        //1、找结束条件:只有一个节点或者没节点的时候结束递归
        if(head==nullptr||head->next==nullptr)
        {
            return head;
        }
        //3、找当前执行语句:实现两个节点交换
        //下面的任务便是交换这3个节点中的前两个节点
        ListNode* second=head->next;//记录第二个节点,不然会找不到
        head->next=swapPairs(second->next);
        //头节点指向第三个节点,第三个节点是待处理的节点,它需要继续递归,传入的是它当前的头节点,即second->next
        second->next=head;
        //2、找返回值,返回的是当前这层递归结束后的头节点,这里是next
        return second;//返回second,因为此时的头节点已经变成了second
    }
};

方法二:迭代


思路与算法
迭代法主要思路就是:通过循环两两交换节点

1、设置一个虚拟头节点dummary_head,并使dummary_head的next指向头节点,代码如下: ListNode* dummy_head=new ListNode(0); dummy_head->next=head;

2、如果直接对虚拟头节点进行操作的话,随着交换会使得交换后新的头节点位置不清除,所有需要设置一个操作节点,使其初始值和虚拟节点相同。 ListNode* cur=dummy_head;

3、通过循环进行节点交换,先考虑什么时候停止循环,当操作节点的下一个节点或下下个节点为空时,停止循环。如图所示:

leetcode24. 两两交换链表中的节点(三种解答方法)_第2张图片

4、判断返回类型,由于在交换时,虚拟头节点的位置不变,其next指向的永远是新的头节点,所以return dummy_head->next;

/**
 * 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* swapPairs(ListNode* head) {
        ListNode* dummy_head=new ListNode(0);
        dummy_head->next=head;
        ListNode* cur=dummy_head;
        while(cur->next!=nullptr&&cur->next->next!=nullptr)
        {
            ListNode* temp=cur->next->next->next;
            ListNode* temp1=cur->next;
            cur->next=cur->next->next;
            cur->next->next=temp1;
            temp1->next=temp;
            cur=cur->next->next;
        }
        return dummy_head->next;
    }
};

 

方法三:双指针
思路与算法
1、双指针法中,定义first和second两个节点,将first节点赋值为head,second节点的位置用于是first->next。 2、由于直接对first进行操作,因此first的位置一直在改变,无法确定新的头节点在哪,因此需要进行判断,如果链表中只有一个节点或链表中没有节点,直接return head; 3、只有当链表中节点大于等于2时,才能继续进行,否则在执行head=first->next;这一步操作会对空节点进行操作,语法错误。 4、通过循环进行节点交换,先考虑什么时候停止循环,当first节点或下个节点为空时,停止循环。如图所示:

leetcode24. 两两交换链表中的节点(三种解答方法)_第3张图片

 

/**
 * 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* swapPairs(ListNode* head) {
        if(head==nullptr||head->next==nullptr) return head;
        ListNode* first=head;
        ListNode* temp=first;
        ListNode* second=nullptr;
        head=first->next;
        while(first!=nullptr&&first->next!=nullptr)
        {
            second=first->next;
            first->next=second->next;
            second->next=first;
            if(temp->next==second->next)
            {
                temp->next=second;
            }
            temp=first;
            first=first->next;
        }
        return head;
    }
};

你可能感兴趣的:(链表,数据结构,算法,leetcode,c++)