作者简介:大家好,我是未央;
博客首页:************************************************************************************************************************************************************************************************************************************************************未央.303****************************************************************************************************************************************************************************************************************************************************************
系列专栏:牛客面试必刷TOP101****
每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!!!
前言
一、链表的奇偶重排
题目描述
描述:
给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。
注意:是节点的编号而非节点的数值。
数据范围:节点数量满足 0≤n≤10^5,节点中的值都满足 0≤val≤1000;
要求:空间复杂度 O(n),时间复杂度O(n)。
示例1:
示例2:
**备注:**链表长度不大于200000。每个数范围均在int内。
题目解析
解题思路:
题目主要信息:
- 给定一个链表,将奇数位的节点依次连在前半部分,偶数位的节点依次连在后半部分;
- 返回连接后的链表头;
方法:双指针(推荐使用)
思路:
如下图所示,第一个节点是奇数位,第二个节点是偶数,第二个节点后又是奇数位,因此可以断掉节点1和节点2之间的连接,指向节点2的后面即节点3,如红色箭头。
如果此时我们将第一个节点指向第三个节点,就可以得到那么第三个节点后为偶数节点,因此我们又可以断掉节点2到节点3之间的连接,指向节点3后一个节点即节点4,如蓝色箭头。那么我们再将第二个节点指向第四个节点,又回到刚刚到情况了。
代码:
java//odd连接even的后一个,即奇数位 odd.next = even.next; //odd进入后一个奇数位 odd = odd.next; //even连接后一个奇数的后一位,即偶数位 even.next = odd.next; //even进入后一个偶数位 even = even.next;
这样我们就可以使用了两个同方向访问指针遍历解决这道题。
解题步骤:
- step 1:判断空链表的情况,如果链表为空,不用重排。
- step 2:使用双指针odd和even分别遍历奇数节点和偶数节点,并给偶数节点链表一个头。
- step 3:上述过程,每次遍历两个节点,且even在后面,因此每轮循环用even检查后两个元素是否为NULL,如果不为再进入循环进行上述连接过程。
- step 4:将偶数节点头接在奇数最后一个节点后,再返回头部。
图示过程解析:
代码编写:
二、删除有序链表中重复的元素-II
题目描述
描述:
给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
举例说明:
给出的链表为1→2→3→3→4→4→5, 返回1→2→5.
给出的链表为1→1→1→2→3, 返回2→3.
数据范围:链表长度 0≤n≤10000,链表中的值满足∣val∣≤1000
要求:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(1),时间复杂度 O(n)
示例1:
示例2:
题目解析
解题思路:
题目的主要信息:
- 在一个非降序的链表中,存在重复的节点,删除该链表中重复的节点
- 重复的节点一个元素也不保留
方法:直接遍历比较删除(推荐使用)
思路:
这是一个升序链表,重复的节点都连在一起,我们就可以很轻易地比较到重复的节点,然后将所有的连续相同的节点都跳过,连接不相同的第一个节点。
代码:
java//遇到相邻两个节点值相同 if(cur.next.val == cur.next.next.val){ int temp = cur.next.val; //将所有相同的都跳过 while (cur.next != null && cur.next.val == temp) cur.next = cur.next.next; }
解题步骤:
- step 1:给链表前加上表头,方便可能的话删除第一个节点。
- step 2:遍历链表,每次比较相邻两个节点,如果遇到了两个相邻节点相同,则新开内循环将这一段所有的相同都遍历过去。
- step 3:在step 2中这一连串相同的节点前的节点直接连上后续第一个不相同值的节点。
- step 4:返回时去掉添加的表头。
图示过程解析:
代码编写: