02链表下:面试中常用到的链表算法(熟悉链表操作)

1. 删除链表中倒数第n个节点(leetcode19)

思路:两指针法,前一个指针先走n步,然后两个指针一起走,当前一个指针走到链尾时,后一个指针正好位于待删除节点的上一个节点

复杂度分析:时间复杂度o(n),空间复杂度o(1)

注意:对链表只有一个节点时边界情况的考虑及处理方式

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode flag_head = new ListNode(0, head);    //生成一个节点,该节点的下一个节点指向链表的头结点
        ListNode fast = head;                      //生成一个快指针,指向头结点
        ListNode slow = flag_head;                   //慢节点指向一开始生成的节点
        int i = 0;
        while(i < n){                             //快指针先走n步
            fast = fast.next;                    
            i++;
        }
        while (fast != null) {                   //两个指针同步伐走
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;             //删除倒数第n个节点
        ListNode ans = flag_head.next;          //将标记的head的值返回
        return ans;
    }
}

 

2. 两个有序链表合并(leetcode21)

思路:可以使用链表的特性将两个链表合并,使用pre节点作为合并链表的标记指针

复杂度分析:时间复杂度o(n+m),其中n和m分别为两条链表的长度,空间复杂度为o(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode forHead = new ListNode();
        ListNode pre = forHead;
        while(l1 != null && l2 != null){
            if(l1.val<=l2.val){     
                pre.next = l1;
                l1 = l1.next;
            }else{
                pre.next = l2;
                l2 = l2.next;
            }
            pre = pre.next;
        }
        pre.next = l1==null? l2:l1;   //将其中一条有剩余元素的链表直接加到合并链表末端
        return forHead.next;
    }
}

3. 链表中环的检测(leetcode141)

思路分析:两指针法,分为快慢两个指针,慢的指针每次走一步,快的指针每次走两步,如果两个指针最后相遇这说明有环,如果直到快指针走到了链表尾两个指针还没相遇,这说明无环。

复杂度分析:时间复杂度o(n),空间复杂度o(1)

注:思考开始时赋初值的方法,快指针为什么不和慢指针同步出发(即fast=slow=head)?

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == 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;
    }
}

4. 单链表反转(leetcode206)

思路:单链表反转的关键是为了防止链断,我们需要使用一个temp节点将标记指针的next节点记住

复杂度分析:时间复杂度o(n),空间复杂度o(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode  tempNode = cur.next;  //防止链断裂 
            cur.next = pre;
            pre = cur;
            cur = tempNode;
        }
        return pre;
    }
}

 

5. 求链表的中间节点(leetcode876)

思路:与回文串属于同一题型,用两指针法

复杂度分析:时间复杂度o(n),空间复杂度o(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast !=null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值