单链表的几个题目题解

简介: 单链表的几个题目题解

关于单链表的题目及题解

第一题移除链表元素

移除链表元素

这题大意是给一串链表,和一个数字key,如果链表中有和key相同的数组就删除,最后返回链表新的头结点。

我们该如何完成这道题?

首先我们应该考虑到如果这个链表为空怎么办?所以我们先要进行特别判断

if(head == null){
  return null;
}

题目中要求的是删除6这个数字

我们可以定义连个引用,首先让cur引用来判断是否是key,而prve这个引用是用来保存cur这个引用前一个引用的,这样就可以实现删除保存的数字是key这个节点了。

如果cur.val == key,则让prve的下个地址为cur的下个地址,如果不等于就把cur这个地址赋值给prve

具体我们看上面的图就可以理解了

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode cur = head;
        ListNode prve = head;
        if(head == null) {
            return null;
        }
        while(cur != null) {
            if(cur.val == val) {
                prve.next = cur.next;
            }else {
                prve = cur;
            }
            cur = cur.next;
        }
        if(head.val == val) {
            return head.next;
        }
        return head;
    }
}

第二题反转链表

反转链表

这题大意是给我们一个链表,然后让我们逆序打印出来

通常有的人就是这样想的,我们可以先将链表中的数字都存到数组里面,然后打印,但这样不是真正的逆序,如果面试题是这样,我们这样操作的话,只会显得我们的水平很菜,所以我们应该从内部让它真正的实现逆序。

假设原来链表如上图所示,我们要变为如下:

首先肯定是将1的地址改为null,不然打印的时候就无法停止下来

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode cur = head;
        ListNode prve = null;
        while(cur != null) {
            ListNode curNext = cur.next;
            cur.next = prve;
            prve = cur;
            cur = curNext;
        }
        return prve;
    }
}

观察代码我们可以发现,这其实就是一个循环实现头插的过程。并且每行代码都是环环相扣的

第三题链表的中间节点

链表的中间节点

这题大意就是给一个链表,返回中间的节点,链表长度是个偶数,就返回第二个节点。

我们想到一个知识,如果速度是另一个速度的2倍,则路程也是,如果这样的话,我们定义一个快的指针,和一个慢的指针,这样当快的指针走到最后的时候,慢的指针是不是刚好走到中间那

class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {//这个地方为什么要考虑fast.next呢?原来下面有个fast.next.next;
            fast = fast.next.next;//如果不考虑则会造成空指针异常
            slow = slow.next;
        }
        return slow;
    }
}

第四题链表中的倒数第k个节点

链表中的倒数第k个节点

这题大意就是输入一个数字k,打印他的倒数第k个节点

我们这样想

假设一共有7个节点

打印倒数第3个节点前面隔了2个

打印倒数第5个节点前面隔了4个

打印倒数第7个节点前面隔了6个

我们是不是可以这样,首先定义两个节点,让快的节点先走k-1步,然后两个节点一起往前移动,

具体可以自己画图体会体会

注意这道题k的长度可能大于链表的长度

public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        ListNode fast = head;
        ListNode slow = head;
        if(k < 0 || head == null) {
            return null;
        }
        while(k-1 != 0) {
            fast = fast.next;
            if(fast == null) {
                return null;
            }
            k --;
        } 
        while(fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

第五题将两个有序链表变为一个有序链表

将两个有序链表变为一个有序链表

合并两个有序,我们要重新开一个新的节点,来表示新的头

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode newHead = new ListNode(-1);
        ListNode tmp = newHead;
        while(list1 != null && list2 != null) {
            if(list1.val < list2.val) {
                tmp.next = list1;
                list1 = list1.next;
                tmp = tmp.next;
            }else {
                tmp.next = list2;
                list2 = list2.next;
                tmp = tmp.next;
            }
        }
        if(list1 == null) {
            tmp.next = list2;
        }
        if(list2 == null) {
            tmp.next = list1;
        }
        return newHead.next;
    }
}

第六题链表分割

链表分割

这个题的大致意思就是输入一个数x,将所有小于x的数都放在左边,大于x的数都放在右边

public class Partition {
    public ListNode partition(ListNode Head, int x) {
        // write code here
        ListNode bs = null;
        ListNode be = null;
        ListNode as = null;
        ListNode ae = null;
        ListNode cur = Head;
        while(cur != null) {
            if(cur.val < x) {
                if(bs == null) {
                    bs = cur;//表示x的左边
                    be =cur;
                }else {
                    be.next = cur;
                    be = be.next;
                }
            }else {
                if(as == null) {
                    as = cur;//表示x的右边
                    ae = cur;
                }else {
                    ae.next = cur;
                    ae = ae.next;
                }
            }
            cur = cur.next;
        }
        if(bs == null) {//如果bs==null 则说明没有小于x的数
            return as;
        }
        be.next = as;
        if(as != null) {//如果as有数,则需要将ae赋值为null,否则打印链表就不能停止
            ae.next = null;
        }
        return bs;
    }
}

以上6道题都是链表的基础题,自己掌握的也不算太精湛,各种细节可能处理不到希望各位指正。

还需要解决的问题:

就是明白为什么有的遍历链表条件是cur != null 而有的是 cur.next != null。

下篇文章的网址


相关文章
【LeetCode题目详解】(三)21.合并两个有序链表、141.环形链表、142.环形链表Ⅱ
【LeetCode题目详解】(三)21.合并两个有序链表、141.环形链表、142.环形链表Ⅱ
106 0
|
测试技术
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
86 0
|
2月前
|
存储
链表题目练习及讲解(下)
链表题目练习及讲解(下)
29 9
|
2月前
链表题目练习及讲解(上)
链表题目练习及讲解(上)
30 1
|
6月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
6月前
|
SQL 算法 数据可视化
LeetCode题目92:反转链表ll 【python 递归与迭代方法全解析】
LeetCode题目92:反转链表ll 【python 递归与迭代方法全解析】
|
7月前
题目----力扣--移除链表元素
题目----力扣--移除链表元素
44 1
|
6月前
|
算法
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
|
6月前
|
存储 SQL 算法
LeetCode 题目 82:删除排序链表中的重复元素 II
LeetCode 题目 82:删除排序链表中的重复元素 II
|
6月前
|
算法 数据挖掘 Python
LeetCode题目25 hard:K个一组翻转链表 【分治策略 Python】
LeetCode题目25 hard:K个一组翻转链表 【分治策略 Python】