OJ题目链接
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点
创建 ListNode cur = head.next 节点。
创建 ListNode prev = head 节点,一直指向 cur 前一个节点。
(若要删除 cur 必须知道 cur 前一个节点,因此定义 prev节点)
- 使 cur 和 prev 节点同时向后遍历,遇到 cur.val == val 再进行删除操作。
代码实现如下:
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null) {
return null;
}
ListNode cur = head.next;
ListNode prev = head;
while(cur != null) {
if(cur.val == val) {
prev.next = cur.next;
} else {
prev = prev.next;
}
cur = cur.next;
}
if(head.val == val) {
head = head.next;
}
return head;
}
}
OJ题目链接
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
- 定义两个指针: head 和 cur ;head在前 cur 在后。
- 每次让 cur 的 next 指向 head,实现一次局部反转。
- 局部反转完成之后,head和 cur 同时往前移动一个位置。
代码实现如下:
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode cur = head.next;
head.next = null;
while(cur != null) {
ListNode curNext = cur.next;
cur.next = head;
head = cur;
cur = curNext;
}
return head;
}
}
OJ题目链接
给你单链表的头结点 head
,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
使用两个指针变量 fast 和 slow,刚开始都位于链表的头结点,slow 一次只走 1 步, fast 一次只走 2 步,一个在前,一个在后,同时走。当 fast.next == null 或 fast == null 时,慢指针就来到了链表的中间位置。
代码实现如下:
class Solution {
public ListNode middleNode(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
OJ题目链接
描述
输入一个链表,输出该链表中倒数第k个结点。
示例1
输入:1,{1,2,3,4,5}
返回值:{5}
fast 指针先跑,当 fast 指针跑了k-1个节点后,slow 指针开始跑
当 fast 指针跑到最后时,slow 所指指针就是倒数第k个节点
代码实现如下:
public class Solution {
public ListNode FindKthToTail(ListNode head, int k) {
if(k <= 0 || head == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
for(int i = 0; i < k - 1; i++ ) {
fast = fast.next;
if(fast == null) {
return null;
}
}
while(fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
OJ题目链接
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
建立一个新链表,用来存放通过拼接给定的两个链表的所有节点组成的。先确定头结点为 newHead 。
接着用循环比较两个链表 list1 和 list2 的头结点 val 值的大小,小的存在newHead后面。
代码实现如下:
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode newHead = new ListNode();
ListNode tmpH = newHead;
while(list1 != null && list2 != null){
if(list1.val < list2.val) {
tmpH.next = list1;
tmpH = list1;
list1 = list1.next;
}else {
tmpH.next = list2;
tmpH = list2;
list2 = list2.next;
}
}
if(list1 != null){
tmpH.next = list1;
}
if(list2 != null){
tmpH.next = list2;
}
return newHead.next;
}
}
OJ题目链接
描述
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。
先令cur=head,把链表分成两段,bs为小于目标值的,as为大于等于目标值的
让cur遍历链表并判断节点放入哪一段里,直到cur==null;
若cur.val
=x,一样的方法 循环结束后把as尾插到be,返回bs
代码实现如下:
public class Partition {
public ListNode partition(ListNode pHead, int x) {
// write code here
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
ListNode cur = pHead;
while (cur != null) {
if(cur.val < x) {
if(bs == null) {
bs = cur;
be = cur;
}else{
be.next = cur;
be = cur;
}
}else{
if(as == null){
as = cur;
ae = cur;
}else{
ae.next = cur;
ae = cur;
}
}
cur = cur.next;
}
if(bs == null){
return as;
}
be.next = as;
if(as != null){
ae.next = null;
}
return bs;
}
}
OJ题目链接
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1
返回:true
- 先找到中间节点。(可以参考上文 3.链表的中间节点)
- 后半段进行翻转。(参考上文 2.翻转链表)
- 前半段与后半段进行比较是否相同。 (循环比较)
代码实现如下:
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
// write code here
//1.找到中间节点
ListNode fast = A;
ListNode slow = A;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
//2.后半段进行翻转
ListNode cur = slow.next;
while(cur != null){
ListNode curNext = cur.next;
cur.next = slow;
slow = cur;
cur = curNext;
}
//3.进行比较
while(A != slow){
if(A.val != slow.val){
return false;
}
if(A.next == slow){
return true;
}
A = A.next;
slow = slow.next;
}
return true;
}
}
OJ题目链接
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
先用计数器遍历两个单链表,得到两个链表的长度,由于不确定 A 与 B 哪个长,因此要进行判断。
求完长度后作差,然后使较长的链表向后走 |A - B|个节点。
以上操作完成后,使两个链表同时向后走,直至 A == B。
代码实现如下:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null){
return null;
}
ListNode pLong = headA;
ListNode pShort = headB;
int len1 = 0;
int len2 = 0;
while(pLong != null){
len1++;
pLong = pLong.next;
}
while(pShort != null){
len2++;
pShort = pShort.next;
}
pLong = headA;
pShort = headB;
int len0 = len1 - len2;
if(len0 < 0){
pLong = headB;
pShort = headA;
len0 = len2 - len1;
}
while(len0 != 0){
len0--;
pLong = pLong.next;
}
while(pLong != pShort){
pLong = pLong.next;
pShort = pShort.next;
}
return pLong;
}
}
OJ题目链接
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
设置两个指针 fast 和 slow,fast一次走两个节点 ,slow一次走一个节点。若果链表内存在环则 fast 和 slow 早晚会相遇。
则这道题只需要让两个指针不断往后走,直到 fast 和 slow相遇,说明存在环,反之不存在环。
代码实现如下:
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null){
return false;
}
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
return true;
}
}
return false;
}
}
ps:这道题很经典,面试的时候若果出现链表题 ,考这道题的几率也非常非常较大
OJ题目链接
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
:happy:这道题用到一点点初中数学
- 先找到相遇点(参照上文环形链表I)。
- fast指针回到起始点。
- 使 fast 和 slow 不断向后走,直到相遇,得到入口点。
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null){
return null;
}
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
break;
}
}
if(fast == null || fast.next == null){
return null;
}
fast = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}
}