算法修炼之路——【链表】Leetcode24 两两交换链表中的节点
题目描述
给定一单链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是简单的改变节点内部的值,而是需要实际的进行节点交换。
示例:
输入:head = [1, 2, 3, 4]
输出:head = [2, 1, 4, 3]
解题思路
我们通过示例可以简单了解到,需要两两进行位置互换,但是互换的动作需要涉及到前置节点与后置节点。这里为方便理解,我们先单独给出四个节点:

图1
见图1所示,我们在T1时刻交换[1, 2]两个节点,T2时刻交换[3, 4]。
这里易看出,此问题可以解为:
- 两两交换
- 迭代两两交换
对于问题1:
我们将总体链表的两两交换位置分别为若干相同的问题1,解法则有:
/*
head = [1, 2, 3, 4]
first, focus [1, 2]
*/
ListNode currHead; // and currHead.next = left leftP.next = rightP.next; // 1->2->3 changed to 1->3
right.next = leftP; // 1->3 changed to 2->1->3
currHead.next = rightP; //upgrate head of piece of this pair
这里涉及到的额外节点信息是两个节点组的前置节点,即currHead;当我们交换[3, 4]时则有:
/*
head = [2, 1, 3, 4]
secod, focus [3, 4] leftP point to 3, rightP 4.
*/
// currHead.next = leftP, here, currHead = ListNode(1) // exchange node 3 and 4
leftP.next = rightP.next;
rightP.next = leftP;
currHead.next = rightP;
对于问题2:
截止到这里,我们已经探索到了问题1的解法,接下来需要做的就是将填补问题1间的缝隙,即将他们融合为一个整体,这里我们容易理解,在交换[3, 4]的时候,需要用到交换[1,2]后的靠后节点(这里为ListNode(1)),则可以理解我们在两两交换时,统一的需要用到currHead, 即两个节点[a, b]中 靠前节点a的前置节点,并需要在[a, b]交换位置后为下一对即将交换的节点更新它们所需的currHead。则我们可以将前两部分代码融合为:
ListNode leftP = head;
ListNode rightP = head.next; ListNode currHead = dummyHead; //for head node // iteration
leftP.next = rightP.next;
rightP.next = leftP;
currHead.next = rightP; //update pos of currHead
currHead = leftP;
步骤罗列
我们已经对问题的解答有了核心的理解,这里将步骤进行进一步梳理:
- 初始化两个指针,一左一右;且为统一规则,采取哨兵机制;
- 迭代:节点交换,并更新下一对节点的靠前前置节点;
- 迭代终止条件为两指针均不为空;终止后返回哨兵节点的下一节点。
解题代码
public static ListNode solutionWithTwoP(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//1. init pointers and dummyHead
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode leftP = head;
ListNode rightP = head.next;
ListNode currHead = dummyHead;
//2. iteration
while (leftP != null && rightP != null) {
// exchange
leftP.next = rightP.next;
rightP.next = leftP;
currHead.next = rightP;
//update pos of currHead
currHead = leftP;
//move forward
leftP = leftP.next;
rightP = leftP == null? null : leftP.next; //attention here
}
return dummyHead.next;
}
复杂度分析
时间复杂度:我们对数据仅进行了一次遍历,所以时间复杂度为O(N);
空间复杂度:我们没有借助额外的容器,所以空间复杂度为常量级O(1)。
GitHub源码
完整可运行文件请访问GitHub。
算法修炼之路——【链表】Leetcode24 两两交换链表中的节点的更多相关文章
- 【算法训练营day4】LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表II
[算法训练营day4]LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表 ...
- [Swift]LeetCode24. 两两交换链表中的节点 | Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head. Example: Given 1->2->3 ...
- LeetCode初级算法--链表02:合并两个有序链表
LeetCode初级算法--链表02:合并两个有序链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...
- python经典面试算法题1.3:如何计算两个单链表所代表的数之和
本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [华为笔试题] 难度系数:⭐⭐⭐ ...
- 算法练习之合并两个有序链表, 删除排序数组中的重复项,移除元素,实现strStr(),搜索插入位置,无重复字符的最长子串
最近在学习java,但是对于数据操作那部分还是不熟悉 因此决定找几个简单的算法写,用php和java分别实现 1.合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两 ...
- Leetcode24.Swap Nodes in Pairs两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 说明: 你的算法只能使用常数的 ...
- LeetCode24 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 说明: 你的算法只能使用常数的 ...
- Leetcode算法系列(链表)之两数相加
Leetcode算法系列(链表)之两数相加 难度:中等给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字.如果,我们将 ...
- [PHP] 算法-合并两个有序链表为一个有序链表的PHP实现
合并两个有序的链表为一个有序的链表: 类似归并排序中合并两个数组的部分 1.遍历链表1和链表2,比较链表1和2中的元素大小 2.如果链表1结点大于链表2的结点,该结点放入第三方链表 3.链表1往下走一 ...
随机推荐
- 安装Kubernetes集群时遇到的问题及解决方法
在搭建Kubernetes集群时遇到一些问题,记录在这里. 搭建过程在另一篇文章:VirtualBox上使用kubeadm安装Kubernetes集群 1. 虚拟机安装完CentOS7登录时遇到war ...
- 达拉草201771010105《面向对象程序设计(java)》第二周学习总结
达拉草201771010105<面向对象程序设计(java)>第二周学习总结 一.理论知识学习部分 这一周我们学习的是书上第三章java的基本程序设计结构的内容,在这一章 ...
- JZOJ 5305. 【NOIP2017提高A组模拟8.18】C (Standard IO)
5305. [NOIP2017提高A组模拟8.18]C (Standard IO) Time Limits: 1000 ms Memory Limits: 131072 KB Description ...
- Docker部署LAMP项目
前言 之前我们学习了如何在Linux部署LAMP项目,今天我们来学习一下如何在Docker下部署LAMP项项目吧! Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条 ...
- 作为一个Tester,你在客户环境能保证质量吗?
公司严格地按照“产品-项目”模式来架构技术部门. 我又测产品,又测项目,所以一方面可以从项目测试的角度发现产品bug,并且给产品提供改进意见,一方面还能测产品为项目赋能,保证项目质量,让项目经理轻松些 ...
- 序列化器:ModelSerializer
ModelSerializer 类提供了一个快捷方式,可让你基于 Models 自动创建一个 Serializer 类,其中的字段与模型类字段对应. ModelSerializer 类与常规 Seri ...
- vue项目使用Vant框架Rem适配(postcss-pxtorem、lib-flexible )的安装使用
1.下载lib-flexible 使用的是vue-cli+webpack,通过npm来安装的 npm i lib-flexible --save 2.引入lib-flexible 在main.js中引 ...
- ajax5
处理跨域方法 (代理) 一个域名地址的组成: /script/jQuery.js 协议 子域名 主域名 端口号 请求资源地址 当协议,子域名,主域名,端口号中任意一个不相同时,都算作不同 ...
- (转)协议森林04 地址耗尽危机 (IPv4与IPv6地址)
协议森林04 地址耗尽危机 (IPv4与IPv6地址) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! IP地址是IP协议的重要组 ...
- react 脚手架装后 运行eject报错 的 正确运行方式
git init git add . git commit -m 'init' npm run eject 或者 cnpm run eject