Leetcode-链表24题:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

题目

  • 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
// An highlighted block
 示例 1: 
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2: 
输入:head = []
输出:[]
示例 3: 
输入:head = [1]
输出:[1]
提示: 
链表中节点的数目在范围 [0, 100]0 <= Node.val <= 100 

解题思路

、首先将问题简单化,如何将两个节点交换位置?

  • 1.如下图创建1个head链表[1,2],其中p和q分别指向需要交换的两个节点。
    在这里插入图片描述
  • 2.翻转两节点步骤:

步骤1:将头指针指向q节点处,以便翻转过来时,头指针(head)依然指向第一个节点。

步骤2:将第一个节点指向第二个节点的下一个节点。
在这里插入图片描述
步骤3:将第二个节点指向第一个节点。整理一下如下图,即翻转成功。
在这里插入图片描述
小结: 以上步骤代码如下:

head = q;
p.next = q.next;
q.next = p;

、回归到题目问题上来,需要两两翻转,无非就是移动p和q指针,然后根据上面的节点交换规则,进行翻转。那么如何移动p和q指针,保证位置正确呢?(创建一个哑节点,时刻来初始化一下p和q的位置)
下面按照题目示例1所示进行解释:

步骤1:创建哑节点or,并指向head节点。创建p和q指针和first指针,初始化p和q的位置,同时都指向哑节点处,first指针指向链表的第二个节点,作为输出的首节点。
代码:

	   //输出用的头节点,即指向第二节点
       ListNode first = head.next;
       //创建哑节点,并指向链表的首节点
       ListNode or = new ListNode();
       or.next = head;
       //创建p,q指针,并指向哑节点初始位置
       ListNode p = or;
       ListNode q = or;

在这里插入图片描述
步骤2:上面已经初始化了,从这开始后面翻转的循环过程。

1)将p指向or节点的下一个节点,即p指向了1节点,再将q指向p的下一个节点,即指向了2节点。
代码:

if(or.next!=null){//初始化p节点位置,保证p指向的不为空
    p = or.next;
}else{
    break;//跳出循环,不用翻转
}
if(p.next!=null){//初始化q节点位置,保证q指向的不为空
    q = p.next;
}else{
    break;//跳出循环,不用翻转
}

在这里插入图片描述
2)根据上面两节点交换位置,规则进行交换。

代码:

p.next = q.next;
q.next = p;

在这里插入图片描述
3)需要将哑节点置于链表首部前面。
代码:

 or.next = q;

在这里插入图片描述

4)将or指针指向p指向的位置,同时也将q指向p的位置,即下一次翻转的初始位置。
代码:

 or = p;
 q = p;

在这里插入图片描述


5)重复1)步骤,即:在这里插入图片描述

6)重复2)步骤,即:在这里插入图片描述
7)重复3)步骤,这里是将节点1指向节点4。在这里插入图片描述
8)重复4)步骤,再循环重复1)步骤,直接跳出循环,返回first链表,即本题的解。
在这里插入图片描述

JAVA代码实现

//leetcode submit region begin(Prohibit modification and deletion)
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
    	//处理空节点
        if(head ==null) return head;
        //处理只有一个节点
        if(head.next == null) return head;
        //输出用的头节点,即指向第二节点
        ListNode first = head.next;
        //创建哑节点,并指向链表的首节点
        ListNode or = new ListNode();
        or.next = head;
        //创建p,q指针,并指向哑节点初始位置
        ListNode p = or;
        ListNode q = or;
        while(p!=null && q!=null){//保证p和q中指向的节点不为空,才可以进行翻转
            if(or.next!=null){//初始化p节点位置,保证p指向的不为空
                p = or.next;
            }else{
                break;
            }
            if(p.next!=null){//初始化q节点位置,保证q指向的不为空
                q = p.next;
            }else{
                break;
            }
            //翻转两节点
            p.next = q.next;
            q.next = p;
            //关联交换位置后的首节点。
            or.next = q;
            //转移到下一个位置的初始。
            or = p;
            q = p;
        }
        return first;
    }
}
//leetcode submit region end(Prohibit modification and deletion)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半点灿烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值