今天是第 天刷leetcode,立个flag,打卡60天。
算法挑战链接
力扣http://24. 两两交换链表中的节点
第一想法
看到题目的第一想法是交换节点,于是赶紧拿出草稿本画了出来。这不简简单单。
1 -> 2 ->3 ->.....
已有的条件:head = node(1)
我只需要将head的节点后的2节点记录下来,然后将head.next 赋值给 3 节点。将2.next 赋值给head节点,这样就完成交换了。
跟随者思路写出代码后提交失败了。~~
主要失败的原因是:head.next 赋值给3节点这个是错误的,因为3节点需要和后面的节点进行交换,因此head.next 应该赋值给交换后的节点。
看完代码随想录之后的想法
使用递归来完成这道题目是一个很不错的选择。
先呈上代码:
/**
* 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 || head.next == null) {
return head;
}
ListNode next = head.next;
//进行递归
ListNode newNode = swapPairs(next.next);
//进行交换
head.next = newNode;
next.next = head;
return next;
}
}
为啥说递归是一个不错的选择,因为我们知道一个局部的操作,这个局部的操作依赖于下一个局部的操作,于是我们可以使用递归,让下一个局部的操作先完成,然后给到我们需要的数据,我们在进行当前的局部操作即可。
当然不递归也是可以完成的。
在不递归的情况下哎我们完成完成交换需要的步骤是三步(如下图)
只需要遍历节点,不断的重复这三个步骤即可完成。(需要注意的点:首节点的操作是不一样,如果不想单独写首节点的操作,可以加入一个哑节点,让后续的操作可以一致。)
代码如下:
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dumyhead = new ListNode(-1); // 设置一个虚拟头结点
dumyhead.next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
ListNode cur = dumyhead;
ListNode temp; // 临时节点,保存两个节点后面的节点
ListNode firstnode; // 临时节点,保存两个节点之中的第一个节点
ListNode secondnode; // 临时节点,保存两个节点之中的第二个节点
while (cur.next != null && cur.next.next != null) {
temp = cur.next.next.next;
firstnode = cur.next;
secondnode = cur.next.next;
cur.next = secondnode; // 步骤一
secondnode.next = firstnode; // 步骤二
firstnode.next = temp; // 步骤三
cur = firstnode; // cur移动,准备下一轮交换
}
return dumyhead.next;
}
}
实现过程中遇到哪些困难
今天在完成题目的过程中忽略掉了后续节点变化的一个流程。导致题目一直没有做对。
今日收获
递归怎么写?写递归前需要明白三点
- 退出递归的条件(递归第一件要完成的事情)
- 进入递归的条件和返回值
- 获取到下一个递归值后的操作
确定好之后,写递归会比较清晰。
用今天这道题来看,我们对应这三个点分别是:
/**
* 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 || head.next == null) {
return head;
}
ListNode next = head.next;
//进入递归的条件和返回值
//进行递归
ListNode newNode = swapPairs(next.next);
获取到下一个递归值后的操作
//进行交换
head.next = newNode;
next.next = head;
return next;
}
}