算法修炼之路——【链表】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往下走一 ...
随机推荐
- 网页程序迁移至微信小程序web-view详解
小程序现在越来越流行,但是公司的很多项目都是用网页写的,小程序语法不兼容原生网页,使得旧有项目迁移至小程序代价很高: 小程序之前开放了webview功能,可以说是网页应用的一大福音了,但是微信的web ...
- OC和C++混编需要注意的问题
文章首发于github.io 2018-12-17 21:01:55 方案一 1. .c文件的identify and type右边栏修改为Objective-C source 2. Built se ...
- 转pdf
一.转印厂pdf(书本类及折页类) 1.储存为(Ctrl+Shift+S) 2.保存类型选择 pdf 3.常规==>Adobe PDF预设==>选择印刷质量 4.选择标记和出血==&g ...
- 设计模式-15命令模式(Command Pattern)
1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...
- 个人项目作业(wc.exe)
1.GitHub项目地址 https://github.com/QiuBin666/WC 项目介绍: 题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行 ...
- C语言程序设计(一) 为什么要学C语言
第一章 为什么要学C语言 学编程的过程,其实就是学习怎样用编程语言说话,让编译器听懂的过程. 汇编语言缺少“可移植性” 除了机器语言和汇编语言以外,几乎所有的编程语言都被统称为高级语言,它的特点是更接 ...
- 深入理解yield from语法
本文目录 为什么要使用协程 yield from的用法详解 为什么要使用yield from . 为什么要使用协程# 在上一篇中,我们从生成器的基本认识与使用,成功过渡到了协程. 但一定有许多人,只知 ...
- mongo密码的设置
MongoDB 版本 v4.0.7 系统 Win10 注意: 要为数据库创建用户,必须先切换到相应的数据库: 要为数据库创建用户,必须先切换到相应的数据库: 要为数据库创建用户,必须先切换到相应的数据 ...
- 2016 Multi-University Training Contest 1 T3
题目要求出所有合法点对间的最短路径的平均值,因此我们应当求出所有合法最短点对的最 短路径之和,再除以合法点对个数. 题目中Guard之间有着很不自然的制约关系,每个Guard的周围和同行.列都不能有其 ...
- Development of a High Coverage Pseudotargeted Lipidomics Method Based on Ultra-High Performance Liquid Chromatography−Mass Spectrometry(基于超高效液相色谱-质谱法的高覆盖拟靶向脂质组学方法的开发)
文献名:Development of a High Coverage Pseudotargeted Lipidomics Method Based on Ultra-High Performance ...