链表面试题1(高频)

链表作为数据结构的重要知识点,通常作为大厂们笔试面试题,这里我写了两篇博客来解决,一共10道题,此篇为前五道题

下篇博客: 后五道题

目录

1. 删除链表中等于给定值 val 的所有节点。

2. 反转一个单链表。

3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

4. 输入一个链表,输出该链表中倒数第k个结点。

5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。


1. 删除链表中等于给定值 val 的所有节点。

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

    }    

方法很简单,主要是对链表便利一遍,节点的val值与给定值相同删除即可,需要注意的是你删除链表节点时需要将现在节点的前驱和后驱进行修改,后驱非常容易获得,前驱就需要我们定义出来,然后定义cur便利数组,由于有前驱的存在,我们从head的下一个节点开始便利,最后对head的值·进行判断即可。


2. 反转一个单链表。

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

        }
        return head;
    }

 要反转我们先把head的next值变为null,在定义cur和curnext,由于翻转可能会丢失后面的几点,所以我们需要定义一个curnext来放置丢失。进入循环先让head往后走一步,再将curnext往后走一步,然后把head的next改为cur,最后cur走到head的位置上。


3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
 

public ListNode middleNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

找链表的中间节点时,我们需要定义两个节点,一个快节点,一次走两步,一个慢节点一次走一步,当快节点走到尾部时,慢节点刚好位于中间。


4. 输入一个链表,输出该链表中倒数第k个结点。
 

public ListNode findKthToTail(ListNode head,int k) {
        //k是否是合法的
        if (k <= 0 || head == null) {
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        while (k - 1 > 0) {
            fast = fast.next;
            k--;
            if (fast == null) {
                return null;
            }
        }
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }

首先我们要对k的值还有head进行合法性检验。找到倒数第k个,我们还是第一两个节点,让fast先走k减一步,再让他两一起走,fast到达最后一个时,slow正好是倒数第k个。注意,fast先走时,如果fast直接走到最后了说明k值过大,返回null。


5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {

        ListNode newNode=new ListNode(-1);
        ListNode tmp=newNode;
        while (list1!=null&&list2!=null){
            if(list1.val<list2.val){
                tmp.next=list1;
                tmp=tmp.next;
                list1=list1.next;
            }else {
                tmp.next=list2;
                tmp=tmp.next;
                list2=list2.next;
            }

        }
        if(list1!=null){
            tmp.next=list1;
        }
        if(list2!=null){
            tmp.next=list2;
        }
        return newNode.next;
    }

要将两个链表拼接为一个有序的输出,首先我们定义一个虚拟的头结点,永远位于头部,再用tmp节点同时便利两个链表,哪个小就把哪个往上拼接即可,知道他两其中一个为空,再分别进行判断,如果不为空,说明是另外一个先走完,直接把剩余的拼接上即可,需要注意的是,如果list1的val值小就list1走,list2不走,而不是两个同时走,这样才能全部比较。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿拉蕾wjh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值