力扣24 两两交换链表中的节点

题目

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

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例:

给定 1->2->3->4,
应该返回 2->1->4->3.



解决方案

  • 思路

首先确定结果头结点的位置,分三种情况

  1. 如果head是空,那么直接返回空指针;
  2. 如果head->next为空,那么只有一个head有效节点,直接返回head;
  3. 当head->next不为空,因为前两个一定交换,那么结果头结点res一定指向head->next;

其中,前两种情况可以合并。

原始 1 2 2 4
两两交换 2 1 4 3

重点:两组之间连上 :即1和4连上


  • 代码

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {

        ListNode* res;  //结果的头结点
        if(!head || !head->next) return head;
        else  res = head->next;

        ListNode* it = head; //注释1
        ListNode *end = it; //交换之后的尾部,为了方便与下一对交换之后的头部相连
        ListNode *temp = nullptr;
        
        while(it && it->next) //注释2
        {
            if(end != it)   end->next = it->next; //注释3
            
            temp = it->next;
            it->next = temp->next;
            temp->next = it;
            end = it;
            it = it->next; 
        }
        
        return res;
}
};
解释
  • 注释1:为什么要用个it指向head,而不直接用head进行移动?
    首先,用head移动是可以的,但是head的话这个词很容易造成误导,词不达意,等一段时间后再看自己的代码,也需要花时间去理解head是中间变量;但是如果用it,很明显是一个临时变量,和temp一样明显,便于理解和阅读,希望大家都能养成好习惯。
  • 注释2:为什么用 it && it->next?
    因为&&(且)运算符是有顺序的,如果前一个为false,则不会判断&&后面的表达式;
    所以如果head为空,那么&&前的表达式结果为false,就不会去判断&&后面的表达式head->next,
    因此就不会出现报错:member access within null pointer of type 'struct ListNode (试图访问空指针)的情况。

        并且这也是判断后续有效结点是否超过两个,超过两个的情况需要交换后续结点,否则不需要。
        例如(1 ->2 ->3) 经过一次while循环。此时已经变成(2 ->1 ->3)不需要其他操作。

  • 注释3: if (end != it)      end->next = it->next  的作用
    (1 2 3 4为例)
    第一次while循环时:end 和 it在同一位置(1),if 判断为false,只进行下面的交换操作,变成(2-> 1      3-> 4)
    第二次while循环时:end指向(1),it 指向(3),此时 if 判断为true,将1和 3后面的4相连,再交换 3 4变成 (2->1->4->3)
    以后的while循环同理。

  • 执行结果

在这里插入图片描述


题解上看见的大神的代码---------双重指针法(呜呜呜我果然还是不行吗)

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
    
        ListNode**it=&head; //注释1
        ListNode *first,*second;
        while((first=*it)&&(second=first->next))
        {
           first->next=second->next;
           second->next=first;
           *it=second;
           it=&(first->next); //注释2
        }
        return head;
}
};
解释
  • 注释1: ListNode**it = &head
    可以修改头指针,it是一个指向head的指针,所以可以通过it修改head的值,上一个解法中 *it=head的话不能修改head的值
    通过这种方式来不对头结点单独处理,所以不需要上一个方法的找头结点res的步骤。

  • 注释2: it = & ( first->next)
    这样的话可以直接修改 first->next 的值,通过 it 而不需要保存 first 的值。

  • 个人想法:双重指针没有一定基础还是不乱用了,写完之后怎么好读怎么写。

发布了15 篇原创文章 · 获赞 1 · 访问量 296

猜你喜欢

转载自blog.csdn.net/Janna_woo/article/details/104672304