链表专项练习


前言

结构越复杂 - 使用越简单 , 结构越简单-使用越复杂; 我愿称之为思考守恒定律
这篇文章主要写 - 链表相关的一些题型以及解题思路 : 这里收录的题只是 , 单纯使用链表的题型不涉及其他的数据结构
一些感想 :

对于做题思路 : 最重要的是写出它的结构流程 ,结构流程图越完备, 写代码就越快 , 所以尽量将结构流程图写好
对于解题方法 : 解题方法不是唯一的,只不过是低效与高效的区分 , 这里尽可能的会多写解题思路与方法,重要的是其后面的思考思路, 以后未必不能优化, 好的算法 与数据结构 就是一步步不断优化过来的 .
对于数据结构 : 没有最好的数据结构 , 只有最适合当前的数据结构 ,要学会自我改动,经典之所以是经典 就是因为它的可扩展性是极大的 .

对于链表 : 链表常见的考察形式为 : 无头 - 单向 - 不循环 , 对于这种结构 : 最大的难点在于, 怎么去寻找它的头结点 , 而我们可以一开始就给这个链表加一个头结点 , 返回的时候再去返回新插入头结点的下一个 - 这样许多做题的思路会很简单

题型1 - 设计一个链表结构

import java.util.List;
import java.util.Stack;

/**
 * @Author 12629
 * @Description: shift+f6(fn+esc)
 */
public class MySingleList {

    static class ListNode {
        public int val;//存储的数据
        public ListNode next;//存储下一个节点的地址

        public ListNode(int val) {
            this.val = val;
        }
    }

    public ListNode head;// 代表当前链表的头节点的引用


    public void createLink() {
        ListNode listNode1 = new ListNode(12);
        ListNode listNode2 = new ListNode(45);
        ListNode listNode3 = new ListNode(23);
        ListNode listNode4 = new ListNode(90);
        listNode1.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4; /* */
        head = listNode1;
    }

    //递归打印链表
    public void display3(ListNode pHead) {
        if(pHead == null) {
            return;
        }
        if(pHead.next == null) {
            System.out.print(pHead.val+" ");
            return;
        }
        display3(pHead.next);
        System.out.print(pHead.val+" ");
    }

    public void display4() {
        Stack<ListNode> stack = new Stack<>();
        ListNode cur = head;
        while (cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        //遍历栈
        while (!stack.isEmpty()) {
            ListNode top = stack.pop();
            System.out.print(top.val+" ");
        }
        System.out.println();
    }


    /**
     * 遍历链表
     */
    public void display() {
        //如果说 把整个链表 遍历完成 那么 就需要 head == null
        // 如果说 你遍历到链表的尾巴  head.next == null
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }

    /**
     * 从指定位置开始打印链表
     * @param newHead
     */
    public void display(ListNode newHead) {
        //如果说 把整个链表 遍历完成 那么 就需要 head == null
        // 如果说 你遍历到链表的尾巴  head.next == null
        ListNode cur = newHead;
        while (cur != null) {
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }

    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = head;
        while (cur != null) {
            if(cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    //得到单链表的长度 O(N)
    public int size(){
        int count = 0;
        ListNode cur = head;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    //头插法 O(1)
    public void addFirst(int data){
        ListNode listNode = new ListNode(data);
        listNode.next = head;
        head = listNode;
    }
    //尾插法 O(N)    找尾巴的过程
    public void addLast(int data){
        ListNode listNode = new ListNode(data);
        if(head == null) {
            head = listNode;
            return;
        }
        ListNode cur = head;
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = listNode;
    }
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data)
            throws ListIndexOutOfException{
        checkIndex(index);
        if(index == 0) {
            addFirst(data);
            return;
        }
        if(index == size()) {
            addLast(data);
            return;
        }
        ListNode cur = findIndexSubOne(index);
        ListNode listNode = new ListNode(data);
        listNode.next = cur.next;
        cur.next = listNode;
    }

    /**
     * 找到 index-1位置的节点的地址
     * @param index
     * @return
     */
    private ListNode findIndexSubOne(int index) {
        ListNode cur = head;
        int count = 0;
        while (count != index-1) {
            cur = cur.next;
            count++;
        }
        return cur;
    }
    private void checkIndex(int index) throws ListIndexOutOfException{
        if(index < 0 || index > size()) {
            throw new ListIndexOutOfException("index位置不合法");
        }
    }

    //删除第一次出现关键字为key的节点 O(N)
    public void remove(int key){
        if(head == null) {
            return ;//一个节点都没有
        }
        if(head.val == key) {
            head = head.next;
            return;
        }
        ListNode cur = searchPrev(key);
        if(cur == null) {
            return;
        }
        ListNode del = cur.next;//要删除的节点
        cur.next = del.next;
    }

    /**
     * 找到关键字key的前一个节点
     * @param key
     * @return
     */
    private ListNode searchPrev(int key) {
        ListNode cur = head;
        while (cur.next != null) {
            if(cur.next.val == key) {
                return cur;
            }
            cur = cur.next;
        }
        return null;//没有你要删除的节点
    }

    //删除所有值为key的节点
    public void removeAllKey(int key){
        if(head == null) {
            return;
        }
        /*while(head.val == key) {
            head = head.next;
        }*/
        ListNode prev = head;
        ListNode cur = head.next;
        while (cur != null) {
            if(cur.val == key) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = cur.next;
            }
        }
        if(head.val == key) {
            head = head.next;
        }
    }

    /**
     * 保证链表当中 所有的节点 都可以被回收
     */
    public void clear() {
        head = null;

        //StringBuilder sb = "fdfa";
    }

    public ListNode reverseList() {
        if(head == null) {
            return null;
        }
        //说明 只有一个节点
        if(head.next == null) {
            return head;
        }
        ListNode cur = head.next;
        head.next = null;

        while (cur != null) {
            ListNode curNext = cur.next;
            //头插法 插入cur
            cur.next = head;
            head = cur;
            cur = curNext;
        }
        return head;
    }

    public ListNode middleNode() {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

    public ListNode findKthToTail(int k) {
        if(k <= 0 || head == null) {
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        //1. fast走k-1步
        while (k-1 != 0) {
            fast = fast.next;
            if(fast == null) {
                return null;
            }
            k--;
        }
        //2、3、
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }

    public boolean chkPalindrome() {
        if(head == null) {
            return false;
        }
        if(head.next == null) {
            return true;
        }
        ListNode fast = head;
        ListNode slow = head;
        //1、找中间节点
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        //2、 翻转
        ListNode cur = slow.next;//代表当前需要翻转的节点
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.next = slow;
            slow = cur;
            cur = curNext;
        }
        //3、一个从头往后  一个从后往前
        while (slow != head) {
            if(head.val != slow.val) {
                return false;
            }
            //偶数的情况
            if(head.next == slow) {
                return true;
            }
            slow = slow.next;
            head = head.next;

        }
        return true;
    }

    public ListNode partition( int x) {
        // write code here
        ListNode bs = null;
        ListNode be = null;
        ListNode as = null;
        ListNode ae = null;

        ListNode cur = head;
        while (cur != null) {
            if(cur.val < x) {
                if(bs == null) {
                    bs = cur;
                    be = cur;
                }else {
                    be.next = cur;
                    be = be.next;
                }
            }else {
                if(as == null) {
                    as = cur;
                    ae = cur;
                }else {
                    ae.next = cur;
                    ae = ae.next;
                }
            }
            cur = cur.next;
        }
        // 有可能不会同时存在小于x 和 大于等于x 的数据
        if(bs == null) {
            return as;
        }
        //第一段不为空
        be.next = as;
        //第2个段为空不为空的问题
        if(as != null) {
            ae.next = null;
        }
        return bs;
    }

    public boolean hasCycle() {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                return true;
            }
        }
        return false;
    }

    public boolean hasCycle1() {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }
        if(fast == null || fast.next == null) {
            return false;
        }
        return true;
    }

    public void createLoop() {
        ListNode cur = head;
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = head.next.next;
    }


    public ListNode detectCycle() {
        ListNode fast = head;
        ListNode slow = head;
        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 = head;
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }

}






题型2 - 反转链表

描述 :给定一个单链表的头结点pHead , 长度为n,反转该链表后,返回新链表的表头。
要求 : 时间复杂度 O(N ) ,空间复杂度 O(1)
在这里插入图片描述

在这里插入图片描述

public ListNode ReverseList(ListNode head) {
         // 不加头结点的方式
         if (head == null || head.next == null ){
             return null;
         }
         ListNode cur=head.next;
         head.next=null;//假如头结点不置于空,那么遍历的时候会出错
         while (cur != null){
             ListNode curNext=cur.next;
             cur.next=head;
             head=cur;
             cur=curNext;
         }
         return head;
     }

在这里插入图片描述

public ListNode ReverseList2(ListNode head) {
        // 加头结点的方式
        if (head == null || head.next == null ){
            return null;
        }
        ListNode pre=new ListNode(-1);
        pre.next = head;
        ListNode cur=head.next;
        head.next  =null;
        while (cur != null){
            head = cur.next;
            cur.next = pre.next;
            pre.next = cur;
            cur =head;
        }
        head = pre.next;
        return head;
    }

链表内指定区间反转

描述 :将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n),空间复杂度 O(1)。
在这里插入图片描述
在这里插入图片描述

解题思路2

public ListNode reverseBetween (ListNode head, int m, int n) {
	//
            //加个表头
            ListNode res = new ListNode(-1);
            res.next = head;
            //前序节点
            ListNode pre = res;
            //当前节点
            ListNode cur = head;
            //找到m
            for(int i = 1; i < m; i++){
                pre = cur;
                cur = cur.next;
            }
            //从m反转到n
            for(int i = m; i < n; i++){
                ListNode temp = cur.next;
                cur.next = temp.next;
                temp.next = pre.next;
                pre.next = temp;
            }
            //返回去掉表头
            return res.next;
        }

链表中的节点每k个一组翻转

描述 : 将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表 , 如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样 , 你不能更改节点中的值,只能更改节点本身。
在这里插入图片描述

    public ListNode reverseKGroup(ListNode head, int k) {
        //先创建一个哑节点
        ListNode dummy = new ListNode(0);
        //让哑节点的指针指向链表的头
        dummy.next = head;
        //开始反转的前一个节点,比如反转的节点范围是[link1,link2],
        //那么pre就是link1的前一个节点
        ListNode pre = dummy;
        ListNode end = dummy;
        while (end.next != null) {
            //每k个反转,end是每k个链表的最后一个
            for (int i = 0; i < k && end != null; i++)
                end = end.next;
            //如果end是空,说明不够k个,就不需要反转了,直接退出循环。
            if (end == null)
                break;
            //反转开始的节点
            ListNode start = pre.next;
            //next是下一次反转的头结点,先把他记录下来
            ListNode next = end.next;
            //因为end是这k个链表的最后一个结点,把它和原来链表断开,
            //这k个节点我们可以把他们看做一个小的链表,然后反转这个
            //小链表
            end.next = null;
            //因为pre是反转链表的前一个节点,我们把小链表[start,end]
            //反转之后,让pre的指针指向这个反转的小链表
            pre.next = reverse(start);
            //注意经过上一步反转之后,start反转到链表的尾部了,就是已经
            //反转之后的尾结点了,让他之前下一次反转的头结点即可(上面分析
            //过,next就是下一次反转的头结点)
            start.next = next;
            //前面反转完了,要进入下一波了,pre和end都有重新赋值
            pre = start;
            end = start;
        }
        return dummy.next;
    }

    //链表的反转
    private ListNode reverse(ListNode head) {
        ListNode pre = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            curr.next = pre;
            pre = curr;
            curr = next;
        }
        return pre;
    }

题型3 - 合并两个排序的链表

描述 :输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
在这里插入图片描述

public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode newHead=new ListNode(-1);
        ListNode tmp;
        //判断是否为空
        if (list1 ==null){
            return list2;
        }
        if (list2 == null){
            return  list1;
        }
        //将头结点给tmp
        if (list1.val <= list2.val) {
            tmp = list1;
            newHead.next = list1;
            list1 = list1.next;

        } else {
            tmp = list2;
            newHead.next = list2;
            list2 = list2.next;
        }
        //依次插入
        while (list1 !=null && list2 !=null ) {
          if (list1.val <= list2.val){
              tmp.next=list1;
              list1=list1.next;
              tmp=tmp.next;
          }else{
              tmp.next=list2;
              list2=list2.next;
              tmp=tmp.next;
          }
        }
        //判断是否有剩余
        if (list1 !=null){
            tmp.next=list1;
        }
        if (list2 !=null){
            tmp.next=list2;
        }
        //删除第一个头结点
        return newHead.next;
    }
合并k个升序的链表

在这里插入图片描述

合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。
解题思路 : 在合并俩个链表的基础上 , 依次调用需要合并的链表 ,

public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode newHead=new ListNode(-1);
        ListNode tmp;
        //判断是否为空
        if (list1 ==null){
            return list2;
        }
        if (list2 == null){
            return  list1;
        }
        //将头结点给tmp
        if (list1.val <= list2.val) {
            tmp = list1;
            newHead.next = list1;
            list1 = list1.next;
 
        } else {
            tmp = list2;
            newHead.next = list2;
            list2 = list2.next;
        }
        //依次插入
        while (list1 !=null && list2 !=null ) {
          if (list1.val <= list2.val){
              tmp.next=list1;
              list1=list1.next;
              tmp=tmp.next;
          }else{
              tmp.next=list2;
              list2=list2.next;
              tmp=tmp.next;
          }
        }
        //判断是否有剩余
        if (list1 !=null){
            tmp.next=list1;
        }
        if (list2 !=null){
            tmp.next=list2;
        }
        //删除第一个头结点
        return newHead.next;
    }
    /**
     * 合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。
     */
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
 
        ListNode list=null;
        for (int i = 0; i < lists.size(); i++) {
            ListNode getlist=lists.get(i);
            list=Merge(list,getlist);
        }
        return list;
    }

题型4 - 判断链表中是否有环

描述 : 判断给定的链表中是否有环。如果有环则返回true,否则返回false。

public boolean hasCycle(ListNode head) {
        if (head == null ){
            return false;
        }
        if( head.next == null){
            return false;
        }
        ListNode fast=head.next.next;
        ListNode slow=head.next;
 
        while( fast !=null && fast.next!=null){
            if (fast == slow || fast.next==slow){
                return true;
            }
            fast=fast.next.next;
            slow=slow.next;
 
        }
        return false;
 
 
    }
判断一个链表是否为回文结构

描述 : 给定一个链表,请判断该链表是否为回文结构。回文是指该字符串正序逆序完全一致。

import java.util.*;
public class Solution {
    //反转链表指针
    ListNode reverse(ListNode head) { 
        //前序节点
        ListNode prev = null; 
        while(head != null){
            //断开后序
            ListNode next = head.next; 
            //指向前序
            head.next = prev; 
            prev = head;
            head = next;
        }
        return prev;
    }
    
    public boolean isPail (ListNode head) {
        ListNode p = head;
        int n = 0;
        //找到链表长度
        while(p != null){ 
            n++;
            p = p.next; 
        }
        //中点
        n = n / 2; 
        p = head;
        //遍历到中点位置
        while(n > 0){ 
            p = p.next;
            n--;
        }
        //中点处反转
        p = reverse(p);  
        ListNode q = head;
        while(p != null){
            //比较判断节点值是否相等
            if(p.val != q.val) 
                return false;
            p = p.next;
            q = q.next;
        }
        return true;
    }
}
判断链表中环的入口节点

给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

     public static ListNode hasCycle1(ListNode head) {
        //先判断链表为空的情况
        if (head == null)
            return null;
        //快慢双指针
        ListNode fast = head;
        ListNode slow = head;
        //如果没环快指针会先到链表尾
        while (fast != null && fast.next != null) {
            //快指针移动两步
            fast = fast.next.next;
            //慢指针移动一步
            slow = slow.next;
            //相遇则有环,返回相遇的位置
            if (fast == slow)
                return slow;
        }
        //到末尾说明没有环,返回null
        return null;
    }
        public ListNode EntryNodeOfLoop(ListNode pHead) {
            ListNode slow = hasCycle1(pHead);
            //没有环
            if(slow == null)
                return null;
            //快指针回到表头
            ListNode fast = pHead;
            //再次相遇即是环入口
            while(fast != slow){
                fast = fast.next;
                slow = slow.next;
            }
            return slow;
        }
}
链表中倒数最后k个结点
import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pHead ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
      public ListNode FindKthToTail (ListNode pHead, int k) {
        if (pHead == null || k<=0){
            return null;
        }
        if (pHead.next == null){
            return pHead;
        }
        
        ListNode fast=pHead;
        ListNode solw=pHead;

        while(k-1>0){
            if (fast.next == null){
                return null;
            }
            fast=fast.next;
            k--;
        }
        while (fast.next != null){
            fast= fast.next;
            solw=solw.next;
        }
        return solw;


    }
}
删除链表的倒数第n个节点

描述 : 给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针

import java.util.*;
public class Solution {
    public ListNode removeNthFromEnd (ListNode head, int n) {
        //添加表头
        ListNode res = new ListNode(-1); 
        res.next = head;
        //当前节点
        ListNode cur = head; 
        //前序节点
        ListNode pre = res; 
        ListNode fast = head;
        //快指针先行n步
        while(n != 0){ 
            fast = fast.next;
            n--;
        }
        //快慢指针同步,快指针到达末尾,慢指针就到了倒数第n个位置
        while(fast != null){
            fast = fast.next;
            pre = cur;
            cur = cur.next;
        }
        //删除该位置的节点
        pre.next = cur.next; 
        //返回去掉头
        return res.next; 
    }
}
两个链表的第一个公共结点

描述 : 输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
          ListNode l1=pHead1;
        ListNode l2=pHead2;
         while (l1 != l2){
            if (l1 == null ){
                l1=pHead2;
            }else {
                l1= l1.next;
            }
            if (l2 == null){
                l2=pHead1;
            }else {
                l2= l2.next;
            }
        }
        return l1;
    }
}

题型5 - 单链表排序

描述: 给定一个节点数为n的无序单链表,对其按升序排序。

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
    /**
     *
     * @param head ListNode类 the head node
     * @return ListNode类
     */
    public ListNode sortInList (ListNode head) {
        //没写完
        if (head == null){
            return null;
        }
        if (head.next == null){
            return  head;
        }
        ListNode tmp=head;
        int n=0;
        while (tmp != null){
            n++;
            tmp=tmp.next;
        }
        int [] array=new int[n];
        tmp=head;
        for (int i = 0; i < n; i++) {
            array[i]=tmp.val;
            tmp= tmp.next;
        }
         Arrays.sort(array);
           tmp=head;
        for (int i = 0; i < n; i++) {
            tmp.val=array[i];
            tmp=tmp.next;
        }

        return  head;

    }
}
链表的奇偶重排

描述 : 给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。注意是节点的编号而非节点的数值。

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode oddEvenList (ListNode head) {
        if (head == null){
            return null;
        }
        if (head.next == null){
            return  head;
        }
        ListNode p=head;
        int n=1;
       ListNode Js=new ListNode(-1);
       ListNode Os=new ListNode(-1);
        ListNode cur = Js;
        ListNode cur1 = Os;
       while (p!=null){

           if (n%2!=0){
               ListNode listNode = new ListNode(p.val);
               cur.next = listNode;
               cur=listNode;
           } else{
               ListNode listNode = new ListNode(p.val);
               cur1.next = listNode;
               cur1=listNode;
           }
           p=p.next;
           n++;
       }
       p=Js;
       while (p.next!=null){
           p=p.next;
       }
       p.next=Os.next;
       return Js.next;
    }
}
删除有序链表中重复的元素-I

删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        // write code here
        if (head == null){
            return null;
        }
        if (head.next == null){
            return  head;
        }
        ListNode pre=new ListNode(-1);
        pre.next=head;
        ListNode p=head;
        while (p != null){
            
            if (pre.val == p.val){
                pre.next=p.next;
                p=pre.next;
                
            }else{
                pre=pre.next;
                p=p.next;
            }
        }

        return head;
    }
}

给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。

import java.util.*;
public class Solution {
    public ListNode deleteDuplicates (ListNode head) {
        //空链表
        if(head == null) 
            return null;
        ListNode res = new ListNode(0);
        //在链表前加一个表头
        res.next = head; 
        ListNode cur = res;
        while(cur.next != null && cur.next.next != null){ 
            //遇到相邻两个节点值相同
            if(cur.next.val == cur.next.next.val){ 
                int temp = cur.next.val;
                //将所有相同的都跳过
                while (cur.next != null && cur.next.val == temp) 
                    cur.next = cur.next.next;
            }
            else 
                cur = cur.next;
        }
        //返回时去掉表头
        return res.next; 
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值