链表进阶详解(链表基础面试题)

目录

单链表反转

链表中环的检测

两个有序的链表合并

删除链表倒数第n个结点

求链表的中间结点


上一篇博客中 -----链表初级详解------我们讲了链表的基本操作,看上去很简单,掌握了基础的增删查改的思想。但这好比三原色,通过各种组合,千变万化。现在我们就看看链表有什么进阶的东西可用学学,了解一下:玩链表,就是玩指针!的具体思想哈哈哈。

 

单链表反转

思路:玩链表就是玩指针,链表的反转其实就是几个指针的移动。我们可以用递归和迭代分别作答。

    private ListNode reverse(ListNode head){
        // 递归到到数第二个节点,返回新的头结点
        if (head.next == null) {
            return head;
        }
        ListNode newHead = reverse(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
//迭代
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null, cur = head;

        while (cur != null) {
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }

        return pre;
    }
}


链表中环的检测

怎么理解这个环结构呢?关键是要想明白,环结构相比无环结构,会有什么新现象。

思路一:一个指针在链表里旅游,去过的地方都标记起来。

               如果存在环结构,指针就会去到以前标记过的地方;

               如果环结构不存在,指针去的一直都是没标记过的地方。

               于是哈希应运而生。

//法一:哈希表
public boolean hasCycle(ListNode head) {
    Set<ListNode> nodesSeen = new HashSet<>();
    while (head != null) {
        if (nodesSeen.contains(head)) {
            return true;
        } else {
            nodesSeen.add(head);
        }
        head = head.next;
    }
    return false;
}

 思路二:两个指针在链表里旅游,一个快一个慢,

               如果存在环结构,两个指针就一定会相遇

               如果不存在环结构,两个指针就一定不会相遇

               就像在操场跑步一样,跑得快的和跑得慢的,一定会相遇,只是不知道跑多少圈才相遇而已。

               于是快慢指针应运而生。

//法二:快慢指针
public boolean hasCycle(ListNode head) {
    if (head == null || head.next == null) {
        return false;
    }
    ListNode slow = head;
    ListNode fast = head.next;
    while (slow != fast) {
        if (fast == null || fast.next == null) {
            return false;
        }
        slow = slow.next;
        fast = fast.next.next;
    }
    return true;
}


两个有序的链表合并

普通的思路可能会新开一个链表,但作为能省就省的我们,还是有更好的方法的(这里不是说能不开辟空间就打死都不开辟,有时候用空间换时间是一种大智慧。)

 public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null) {
            return l2;
        }
        if(l2 == null) {
            return l1;
        }

        if(l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }

 


删除链表倒数第n个结点

这个很简单,用快慢指针就能搞定,让快指针先走n步,

  public ListNode removeNthFromEnd(ListNode head, int n) {
        if(head==null||n<0)  return null;
        ListNode dummy = new ListNode(0);
        dummy.next=head;
        ListNode fast=dummy;
        ListNode slow=dummy;
        for(int i =0;i<=n;i++){
            fast=fast.next;
        }
        while(fast!=null){
            slow=slow.next;
            fast=fast.next;
        }
        slow.next=slow.next.next;
        return dummy.next;
    }

 

求链表的中间结点

这个也很简单,用快慢指针就能搞定,让快指针的速度为慢指针的两倍,这样快指针到底了,慢指针不就刚好停在链表中点处么。

ListNode fast = head;
        ListNode slow = head;
        // 根据快慢指针,找到链表的中点
        while(fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值