经度算法:花式链表中查找

在面试中有关链表的提问,真可谓经久不衰。说实话笔者对算法也是研究不太深,而大多数人更要注重后天的积累(套路见多了就会了),天才毕竟是少数人。上次谈过逆转单向链表,今天将分享单链表中查找:是否存在环以及环入口、寻找中位数、倒数第K个节点。

快慢指针

快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2,慢指针每次向前移动1次。

class Node<T> {
	T value;
	Node<T> next;
	Node(T value) {
		this.value = value;
	}
}

判断单链表是否存在环

思路:如果一个单链表中有环,用一个指针去遍历,永远不会结束,所以可以用两个指针,一个指针一次走一步,另一个指针一次走两步,如果存在环,则这两个指针会在环内相遇,时间复杂度为O(n)。

环入口点

如果有环,当fast若与slow相遇时,slow肯定没有走遍历完链表或者恰好遍历一圈,于是我们从链表头与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。

环儿长度

fast, slow从碰撞点出发再次碰撞就是环儿的长度

public static boolean existRing(Node header) {
    // 定义两个指针fast和slow,fast移动步长为2,slow移动步长为1
    Node fast = header;
    Node slow = header;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        //如果相遇则存在环儿,跳出
        if (fast == slow) {
            break;
        }
    }
    // 根据跳出循环的条件return
    if (fast == null || fast.next == null) {
        return false;
    } else {
        return true;
    }
}
public static Node findRingEntrance(Node header) {
    Node fast = header;
    Node slow = header;
    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;
    }
    slow = header;
    while (slow != fast) {
        slow = slow.next;
        fast = fast.next;
    }
    return slow;
}
public static int ringLength(Node header) {
    // 如果不存在环儿,返回0
    if (!isExistLoop(header)) {
        return 0;
    }
    Node fast = header;
    Node slow = header;
    int length = 0;
    boolean begin = false;
    boolean again = false;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        // 超过两圈后停止计数,跳出循环
        if (fast == slow && again == true) {
            break;
        }
        // 超过一圈后开始计数
        if (fast == slow && again == false) {
            begin = true;
            again = true;
        }
        if (begin == true) {
            ++length;
        }
    }
    return length;
}

寻找中位数、倒数第K个节点

思路大同小异。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值