单链表常见习题总结

33 篇文章 0 订阅

单链表常见习题总结2

10:删除所有关键值为key的节点

//10:删除所有关键值为key的节点
    public void removeAllKey(int key) {
        if (this.head == null) {
            return;
        }
        ListNode prev = this.head;
        ListNode cur = prev.next;//这样就可以一直知道cur的前驱是什么
        //头会漏掉,所以在循环遍历单链表之后再判断一次头就可以了
        while (cur != null) {
            if (prev.next.data == key) {
                prev.next = cur.next;//删除这个节点
                cur = cur.next;//因为prev.next已经被删除了,所以prev不能再走了,只能是cur在走
            } else {
                prev = cur;
                cur = cur.next;
            }
        }
        if (this.head.data == key) {//判断头部是要删除的节点
            this.head = this.head.next;
        }
    }

11:翻转单链表

 //11:翻转单链表:1:记录一个点然后进行头插法:简单明了
    //2:定义四个引用cur curNext(保存头置null) prev(保存好前驱) newHead
    public ListNode reverseList() {
        ListNode cur = this.head;
        ListNode prev = null;
        ListNode newHead = null;
        while (cur != null) {
            ListNode curNext = cur.next;
            if (curNext == null) {
                newHead = cur;
            }
            cur.next = prev;
            prev = cur;
            cur = curNext;
        }
        return newHead;
    }

    public void disPlay1(ListNode newHead) {
        ListNode cur = newHead;
        while (cur != null) {
            System.out.print(cur.data + " ");
            cur = cur.next;
        }
        System.out.println();
    }

12:返回链表的中间结点

//12:返回链表的中间结点
    //1:定义cur走getlength/2的步数:遍历了单链表两次,虽然最后之遍历了单链表半截
    //2:定义快慢指针:速度2倍
    public ListNode middleNode() {
        ListNode fast = this.head;
        ListNode slow = this.head;
        while (fast != null && fast.next != null) {//fast!=null是两个结点的时候,若无会出现空指针异常
            fast = fast.next.next;
            slow = slow.next;//fast走两步,slow走一步
        }
        return slow;//即slow是中间结点
    }

13:倒数第k个节点

  //13:倒数第k个节点
    //1:定义一个引用走单链表长度-k步即(length-k)
    //2:定义快慢指针,快的先走k-1步,也就是fast和slow就是差了k-1步
    public ListNode findKthTOtail(int k) {
        //判断是否合法-1 和6等等类型
        //k>getLength()  6   fast==null,即可以走一步就判断一下fast是否为空即可
        //if(k<=0||k>getLength())
        if (this.head == null || k <= 0) {//判断空的单链表
            return null;
        }
        ListNode fast = this.head;
        ListNode slow = this.head;
        while (k - 1 > 0) {
            if (fast.next != null) {
                fast = fast.next;
                k--;//还没有退出循环fast就为空了,出现空指针异常
            } else {
                System.out.println("没有这个节点");
                return null;
            }
        }//fast先走了k-1步
        while (fast.next != null) {//fast.next==null就找到了slow//k=1时上面循环进不去!!!!!!!!!!
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }

14:给定一个x将小于x 的节点放在大于和等于x节点的前面

//14:给定一个x将小于x 的节点放在大于和等于x节点的前面
    public ListNode partition(int x) {
        ListNode cur = this.head;
        ListNode beforeStart = null;
        ListNode beforeEnd = null;
        ListNode afterStart = null;
        ListNode afterEnd = null;
        while (cur != null) {
            //cur.data < x
            if (cur.data < x) {
                //第一次插入
                if (beforeStart == null) {
                    beforeEnd = cur;
                    beforeStart = cur;
                } else {
                    beforeEnd.next = cur;
                    beforeEnd = beforeEnd.next;

                }
            } else {//大于等于x的
                //第一次插入
                    if (afterStart == null) {
                        afterEnd = cur;
                        afterStart = cur;
                    } else {
                        afterEnd.next = cur;
                        afterEnd = afterEnd.next;
                    }
                }
                cur = cur.next;
            }
        if (beforeStart == null) {//小于x的链表为空
            return afterStart;
        }
        if (afterStart != null) {
            afterEnd.next = null;//满足单链表的最后一个的next域为null
        }
        beforeEnd.next = afterStart;
        return beforeStart;
    }

15:删除重复节点

//15:删除重复的节点:自己
        public ListNode deleteDuplication() {
            ListNode node = new ListNode(-1);
            ListNode cur = this.head;
            ListNode tmp = node;
            while (cur != null) {
                if (cur.next != null &&
                        cur.data == cur.next.data) {
                    //1、循环
                    ListNode cur1 = cur;
                    //不能让它走到尾巴,不然就空指针异常
                    while (cur.next!=null&&cur.data == cur.next.data) {
                        cur = cur.next;
                    }
                    //2、退出循环 cur要多走一步//让他走到尾结点
                    cur = cur.next;
                    //进行删除
                    cur1.next = cur;
                } else {
                    //当前节点 不等于下一个节点的时候
                    tmp.next = cur;
                    cur = cur.next;
                    tmp = tmp.next;
                }
            }
            //temp.next=null;也是可以的
            return node.next;
        }

16:链表回文结构

 //16:链表回文结构
    public boolean chkPalindrome() {
        //1:思想:将后面的进行翻转然后进行陪陪即可
        ListNode fast = this.head;
        ListNode slow = this.head;
        //找到中间位置
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        //只有一个节点的时候,就是回文
        if (this.head == null) {
            return true;
        }
        //循环出来slow的位置就是中间的位置
        //将后半部分进行反转
        ListNode p = slow.next;
        while (p != null) {
            ListNode pNext = p.next;
            //反转
            p.next = slow;
            slow = p;
            p = pNext;
        }
        while (this.head != slow) {//没有相遇
            if (slow.data != head.data) {
                return false;
                //slow往前    head 往后  .data不一样 返回false
                //直到相遇
            } else {
                if (head.next == slow) {//考虑偶数的情况下
                    return true;
                }
                head = head.next;//头往后走
                slow = slow.next;//尾巴slow往前走
            }
        }
        return true;
    }

17:判断链表是否有环

//17:判断链表是否有环
    //思想,定义快慢指针,fast走两步,slow走一步;当fast=slow时,就证明有环
    //1:建成环
    public void creatLoop() {
        ListNode cur = this.head;
        while (cur.next != null) {
            cur = cur.next;
        }//最后一个节点
        cur = cur.next;
    }

    //判断是否有环
    public boolean hasCycle() {
        ListNode fast = this.head;
        ListNode slow = this.head;
        if (this.head == null || this.head.next == null) {
            return false;
        }
        while (fast != null && fast.next != null) {//判断slow是否和fast相等
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                return true;
            }
        }
        return false;
    }

18:判断有环的环的入口

//18:找到环的入口
    //思想:定义快慢指针,相遇一次之后,将其中一个指针指向头节点,然后两个指针同时走,直到两个指针相遇
    //该节点就是环的入口
    public ListNode detectCycle() {
        ListNode fast = this.head;
        ListNode slow = this.head;
        while (fast != slow) {//判断slow是否和fast相等
            if (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 = this.head;
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }//第二次相遇就是环的入口所在的地方
        return fast;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值