链表常见算法

1. 奇偶链表

给定一个单链表,把所有的奇数结点偶数结点分别排在一起,重新链成一个新链表。

注意:不是操作链表中的值。

1->2->3->4,转换成1->3->2->4

解题思路:odd为奇数节点,even为偶数节点,循环遍历,当偶数节点为空时,循环结束。

public static Node oddEvenNode(Node head) {
    //如果只有一个节点
    if(head == null || head.next == null) {
        return head;
    }
    //奇数节点
    Node odd = head;
    //偶数节点
    Node even = head.next;
    //偶数节点的头
    Node eHead = even;
    while(even!=null && even.next!=null) {

        odd.next = even.next;
        odd = odd.next;

        even.next = odd.next;
        even = even.next;
    }
    //将偶数节点的头拼接到奇数节点后面
    odd.next = eHead;

    return head;
}

2. 链表逆置

1->2->3,逆置为3->2->1

我觉得最好理解的是三指针法

public static Node inversion(Node head) {

    //上一节点
    Node pre = null;
    //当前节点
    Node current = head;
    //下一节点
    Node next = null;
    while (current != null) {
        next = current.next;
        //头插
        current.next = pre;
        //上一节点变成当前节点
        pre = current;
        //当前节点变更下一节点
        current = next;
    }
    return pre;
}

3. 环型链表判断

解题思路:使用快慢指针,如果两个指针相遇,则有环。

public static Boolean cycle(Node head) {
    if(head == null || head.next == null) {
        return false;
    }
    //慢指针
    Node slow = head;
    //快指针
    Node fast = head.next;

    while (slow != null && fast.next != null) {
        if(slow.value == fast.value) {
            return true;
        }
        //慢指针走一步
        slow = slow.next;
        //快指针走两步
        fast = fast.next.next;
    }
    return false;
}

4. 两个链表的交点

C1为两个链表的交点

解题思路,循环遍历两个链表的长度,算出两个链表长度的差(gap),让长的链表先走gap步,然后再一起走,如果两个节点的值相等,就是交点。

public static String intersection(Entry node1, Entry node2) {
    if(node1 == null || node2 == null) {
        return null;
    }
    //计算node1的长度
    int node1Length = 1;
    Entry temp = node1;
    while(temp.next != null) {
        node1Length++;
        temp = temp.next;
    }

    //计算node2的长度
    int node2Length = 1;
    temp = node2;
    while(temp.next != null) {
        node2Length++;
        temp = temp.next;
    }

    System.out.println(node1Length);
    System.out.println(node2Length);

    //两个链接长度的差
    int gap = Math.abs(node1Length - node2Length);

    Entry longNode = node1;
    Entry shortNode = node2;
    if(node1Length < node2Length) {
        longNode = node2;
        shortNode = node1;
    }
    //长链表先走gap步
    if(gap > 0) {
        while (gap > 0) {
            longNode = longNode.next;
            gap--;
        }
    }
    //再一起走
    while (longNode!=null && shortNode!=null) {
        if(longNode.value == shortNode.value) {
            return longNode.value;
        }
        longNode = longNode.next;
        shortNode = shortNode.next;
    }
    return null;
}

5. 获取链表的中间节点

解题思路:使用快慢指针,定义两个从头开始的指针,一个一次走一步,另一个一次走两步,也称为快慢指针。当快指针走到空或者快指针的下下个节点为空时就会惊奇的发现慢指针的正好处在中间节点处。

public static int centerNode(Node head) {
    Node slow = head;
    Node fast = head;

    while(fast!=null && fast.next!=null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow.value;
}

6. 两个顺序链表合并

public static Node mergeNode(Node node1, Node node2) {
    Node p = new Node();
    Node current = p;
    while(node1!=null && node2!=null) {

        if (node1.value > node2.value) {
            current.next = node2;
            node2 = node2.next;
        } else {
            current.next = node1;
            node1 = node1.next;
        }
        current = current.next;
    }
    if(node1 != null) {
        current.next = node1;
    }
    if(node2 != null) {
        current.next = node2;
    }
    return p.next;
}

7. 返回倒数第K个节点

解题思路:

* 1.我们先定义一个慢指针slow和一个快指针fast;
* 2.我们先让快指针提前走K位,然后两个指针同时向后走,在走的期间两指针之间始终保持K位
* 3.当fast指针走完整个链表的时候,slow指针所在的节点里面的内容就是倒数第K个节点的值
public static Node lastIn(Node head, int k) {
    Node fast = head;
    Node slow = head;
    while (k > 0) {
        if(fast == null) {
            return null;
        }
        fast = fast.next;
        k--;
    }

    while (fast != null) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

8. 回文链表

1->2->3->2->1

1->2->3->3->2->1

这种就是回文链表

public static Boolean huiwen(Node head) {
    //如果只有一个节点
    if(head==null || head.next == null) {
        return true;
    }
    //只有两个节点
    if(head.next.next == null) {
        if(head.value == head.next.value) {
            return true;
        } else {
            return false;
        }
    }
    //快慢指针
    Node slow = head;
    Node fast = head;
    while (fast.next != null && fast.next.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    //反转fast
    Node p = slow.next;

    //pre为逆置后的链表
    Node pre = null;
    Node current = p;
    Node next = null;
    while (current != null) {
        next = current.next;
        current.next = pre;

        pre = current;
        current = next;
    }

    //head开始,与逆置后的链表比较
     while (pre!=null && pre.next!=null) {
         if (pre.value != head.value) {
             return false;
         }
         pre = pre.next;
         head = head.next;
     }

    return true;
}

 vpn链接,13元一月

https://a.500ml.business/auth/register?code=jClQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值