小白学Java链表第一关——黄金挑战

目录​​​​​​​

1.链表环的问题

1.1链表环的问题——Leetcode141

​​​​​​​​编辑

1.1链表环的问题——Leetcode142

​​​​​​​​编辑

2.双向链表的问题

3.1插入状态

3.2删除元素​​​​​​​


1.链表环的问题

public boolean hasCycle(ListNode head) {
    // 创建一个指针pos,初始指向头节点
    ListNode pos = head;
    // 创建一个集合visited,用于存储已经访问过的节点
    Set<ListNode> visited = new HashSet<ListNode>();
    // 遍历链表
    while (pos != null) {
        // 如果当前节点已经在visited集合中,则说明存在环,返回true
        if (visited.contains(pos)) {
            return true;
        } else {
            // 否则将当前节点加入visited集合中
            visited.add(pos);
        }
        // 指针后移
        pos = pos.next;
    }
    // 如果遍历完整个链表都没有发现环,则返回false
    return false;
}

1.1链表环的问题——Leetcode141

https://leetcode.cn/problems/linked-list-cycle/description/​​​​​​​ 

​​​​​​​

public boolean hasCycle(ListNode head) {
    // 创建一个集合visited,用于存储已经访问过的节点
    Set<ListNode> visited = new HashSet<ListNode>();
    // 遍历链表
    while (head != null) {
        // 如果当前节点已经在visited集合中,则说明存在环,返回true
        if (!visited.add(head)) {
            return true;
        } else {
            // 否则将当前节点加入visited集合中
            visited.add(head);
        }
        // 指针后移
        head = head.next;
    }
    // 如果遍历完整个链表都没有发现环,则返回false
    return false;
}

1.1链表环的问题——Leetcode142

https://leetcode.cn/problems/linked-list-cycle-ii/description/

​​​​​​​

public ListNode detectCycle(ListNode head) {
    // 快慢指针初始指向头节点
    ListNode fast = head, slow = head;
    // 遍历链表,寻找环的起始节点
    while (true) {
        // 如果快指针或者快指针的下一个节点为空,说明不存在环,返回null
        if (fast == null || fast.next == null) {
            return null;
        }
        // 快指针每次移动两步,慢指针每次移动一步
        fast = fast.next.next;
        slow = slow.next;
        // 如果快指针和慢指针相遇,说明存在环,跳出循环
        if (fast == slow) {
            break;
        }
    }
    // 将快指针重新指向头节点
    fast = head;
    // 两个指针相遇的节点即为环的起始节点
    while (slow != fast) {
        slow = slow.next;
        fast = fast.next;
    }
    // 返回环的起始节点
    return fast;
}

2.双向链表的问题

//创建双链表结点
class DoubleNode {
    public int data;    // 数据域,用于存储结点的数据
    public DoubleNode next;    // 指向下一个结点的引用
    public DoubleNode prev;    // 指向上一个结点的引用

    public DoubleNode(int data) {
        this.data = data;    // 构造方法,初始化结点的数据域
    }

    // 打印结点的数据域
    public void displayNode() {
        System.out.print("{" + data + "} ");    // 输出结点的数据域内容
    }
}

 双向链表的结构和遍历

public class DoublyLinkList {
    private DoubleNode first; // 链表的头节点
    private DoubleNode last; // 链表的尾节点
    
    public DoublyLinkList() {
        first = null; // 初始化时,链表为空,头节点和尾节点均为null
        last = first; 
    }
    
    /**
     * 从头部开始遍历并打印链表中的节点
     */
    public void displayForward() {
        System.out.print("List(first--->last): ");
        DoubleNode current = first; // 从头节点开始遍历
        while (current != null) {
            current.displayNode(); // 调用节点的displayNode()方法打印节点信息
            current = current.next; // 移动到下一个节点
        }
        System.out.println();
    }
    
    /**
     * 从尾部开始遍历并打印链表中的节点
     */
    public void displayBackward() {
        System.out.print("List(last--->first): ");
        DoubleNode current = last; // 从尾节点开始遍历
        while (current != null) {
            current.displayNode(); // 调用节点的displayNode()方法打印节点信息
            current = current.prev; // 移动到上一个节点
        }
        System.out.println();
    }
}

3.1插入状态

// 在链表头部插入一个节点
public void insertFirst(int data) {
    DoubleNode newDoubleNode = new DoubleNode(data);
    if (isEmpty()) { // 如果链表为空,新节点既是第一个节点,也是最后一个节点
        last = newDoubleNode;
    } else { // 如果链表不为空,则将原来的第一个节点的prev指针指向新节点
        first.prev = newDoubleNode;
    }
    newDoubleNode.next = first; // 新节点的next指针指向原来的第一个节点
    first = newDoubleNode; // 将新节点赋给first成为第一个节点
}

// 在链表尾部插入一个节点
public void insertLast(int data) {
    DoubleNode newDoubleNode = new DoubleNode(data);
    if (isEmpty()) { // 如果链表为空,新节点既是第一个节点,也是最后一个节点
        first = newDoubleNode;
    } else { // 如果链表不为空,则将原来的最后一个节点的next指针指向新节点
        last.next = newDoubleNode;
        newDoubleNode.prev = last; // 新节点的prev指针指向原来的最后一个节点
    }
    last = newDoubleNode; // 将新节点赋给last成为最后一个节点
}

// 在某个节点后面插入一个节点
public void insertAfter(int key, int data) {
    DoubleNode newDoubleNode = new DoubleNode(data);
    DoubleNode current = first;
    // 遍历链表,找到要插入节点的位置
    while ((current != null) && (current.data != key)) {
        current = current.next;
    }
    if (current == null) { // 如果链表为空或未找到key值,则在链表末尾插入新节点
        if (isEmpty()) { // 如果链表为空,则新节点既是第一个节点,也是最后一个节点
            first = newDoubleNode;
            last = newDoubleNode;
        } else { // 如果链表不为空,则在链表末尾插入新节点
            last.next = newDoubleNode;
            newDoubleNode.prev = last;
            last = newDoubleNode;
        }
    } else { // 如果找到了key值,则在该节点后面插入新节点
        if (current == last) { // 如果key值是最后一个节点,则将新节点插入链表末尾
            newDoubleNode.next = null;
            last = newDoubleNode;
        } else { // 如果key值不是最后一个节点,则将新节点插入当前节点和下一个节点之间
            newDoubleNode.next = current.next;
            current.next.prev = newDoubleNode;
        }
        current.next = newDoubleNode;
        newDoubleNode.prev = current;
    }
}

3.2删除元素

// 检查链表是否为空
public boolean isEmpty() {
    return (first == null);
}

// 从头部删除结点
public DoubleNode deleteFirst() {
    DoubleNode temp = first;
    if (first.next == null) { // 如果链表只有一个节点,删除后链表为空,将last指向null
        last = null;
    } else { // 如果链表有两个(包括两个)以上的节点,则将第二个节点的prev指针指向null
        first.next.prev = null;
    }
    first = first.next; // 将第二个节点赋给first成为第一个节点
    return temp; // 返回删除的节点
}

// 从尾部删除结点
public DoubleNode deleteLast() {
    DoubleNode temp = last;
    if (first.next == null) { // 如果链表只有一个节点,则删除后为空链表,将first指向null
        first = null;
    } else { // 如果链表有两个(包括两个)以上的节点,则将倒数第二个节点的next指针指向null
        last.prev.next = null;
    }
    last = last.prev; // 将倒数第二个节点赋给last成为最后一个节点
    return temp; // 返回删除的节点
}

// 按值删除
public DoubleNode deleteKey(int key) {
    DoubleNode current = first;
    // 遍历链表,找到要删除节点的位置
    while (current != null && current.data != key) {
        current = current.next;
    }
    if (current == null) { // 如果当前节点为空,则返回null,说明链表中没有要删除的节点
        return null;
    } else {
        if (current == first) { // 如果要删除的节点是第一个节点
            first = current.next; // 将第二个节点赋给first成为第一个节点
            current.next.prev = null; // 将第二个节点的prev指针指向null
        } else if (current == last) { // 如果要删除的节点是最后一个节点
            last = current.prev; // 将倒数第二个节点赋给last成为最后一个节点
            current.prev.next = null; // 将倒数第二个节点的next指针指向null
        } else { // 如果要删除的节点不是第一个节点也不是最后一个节点
            current.prev.next = current.next; // 将当前节点的上一个节点的next指针指向当前节点的下一个节点
            current.next.prev = current.prev; // 将当前节点的下一个节点的prev指针指向当前节点的上一个节点
        }
    }
    return current; // 返回删除的节点
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值