常见链表面试题 (java语言版)

一、逆置反转单链表

例如:操作前:1 2 3 4 null

          操作后: 4 3 2 1 null

方法一:

 

 

public ListNode reverseList_01(ListNode head) {
            ListNode result = null;
            ListNode cur = head;

            while (cur != null) {
                ListNode node = cur.next;

                cur.next = result;
                result = cur;

                cur = node;
            }
            return result;
        }

方法二:

public ListNode reverseList_02(ListNode head) {
            ListNode prev = null;
            ListNode cur = head;
            ListNode next = head.next;

            while (cur != null) {
                cur.next = prev;
                //整体后移
                prev = cur;
                cur = next;
                if (next != null) {
                    next = next.next;
                }
            }
            return head;
        }

 

二、删除链表中等于给定值 val 的所有节点

方法一:

 1、创建一个新的链表 result
 每遍历一个结点  拿去与 val 比较
 如果不相等  则尾插到 result 中
 相等则继续往后走
//思路与第一题雷同


public ListNode removeElements(ListNode head, int val) {
            ListNode result = null;
            ListNode cur = head;
            ListNode lastNode = null;//结果链表的最后一个结点

            while (cur != null) {
                ListNode node = cur.next;
                if (cur._value != val) {

                   // cur.next = null;
                    if (result == null) {
                        result = cur;
                    } else {
                        lastNode.next = cur;
                    }

                    lastNode = cur;//更新:此时链表的最后一个结点变成了刚刚尾插进来的cur
                }
                cur = node;
            }
            return result;
        }

方法二:

            就地查找并删除

 

public ListNode removeElements111(ListNode head, int val) {

            ListNode cur = head.next;
            ListNode pre = head;
            if (head == null) {
                return null;
            }

            while (cur != null) {
                if (cur._value == val) {
                    //如果是则删除(跳过)该结点pre.next 便指向 cur.next;
                    pre.next = cur.next;
                    cur = cur.next;
                    continue;
                }
                pre = cur;//更新
                cur = cur.next;
            }
            return head;
        }

 

三、以给定值x为基准将链表分割成两部分所有小于x的结点排在大于或等于x的结点之前
且顺序不变

例如:操作前: 3 5 2 1 4 8           x=5
      操作后: 3 2 1 4  5  8


 

public ListNode fenGe(ListNode pHead, int x) {
            ListNode small = null;
            ListNode smallLast = null;
            ListNode big = null;
            ListNode bigLast = null;

            ListNode cur = pHead;
            while (cur != null) {
                ListNode next = cur.next;

                // 小于 x,尾插到 small,大于等于 x,尾插到 big
                if (cur._value < x) {

                    cur.next = null;
                    if (small == null) {
                        small = cur;
                    } else {
                        smallLast.next = cur;
                    }
                    smallLast = cur;

                } else {
                    cur.next = null;
                    if (big == null) {
                        big = cur;
                    } else {
                        bigLast.next = cur;
                    }
                    bigLast = cur;
                }
                cur = cur.next;
            }
            /**
             * 合并small 与 big 两个链表
             */
            //如果有链表为空
            if (small == null) {
                return big;
            } else {
                smallLast.next = big;
                return small;
            }
        }

    }

四、删除所有重复的value

/**
 * 例如:删除前:1 3 3 4 5 5 6
 *      删除后:1 4 6
 */

 

public ListNode deletDoplicate(ListNode head) {
        if (head == null) {
            return null;
        }
        //创建一个假结点,用于Prev所指
        /**
         * 创建假结点,便于处理 第一个结点重复,需删除的情况
         * 消除第一个结点没有前驱的特殊性
         */
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;// prev 永远是 p1 的前驱结点,用来删除结点

        ListNode p1 = head;
        ListNode p2 = head.next;
        while (p2 != null) {
            //在不重复的情况下,三个引用 同时往后走
            if (p1._value != p2._value) {
                p1 = p1.next;
                p2 = p2.next;
                prev = prev.next;
            } else {
            //一但重复,则p2后走,p1不动,继续比较,直到不等,进行删除
                while (p2 != null && p2._value == p1._value) {
                    p2 = p2.next;
                }
                prev.next = p2;
                p1 = p2;
            }
            if (p2 != null) {
                p2 = p2.next;
            }
        }
        return dummy.next;
    }

五、合并两个有序链表,合并完依然有序

/**
* 创建一个新链表result
* 比较L1.value 与L2.value
* 谁小谁尾插到result上
*/
例如:L1:1 3 5 6
L2:1 2 6 8
result:1 1 2 3 5 6 6 8

 

public ListNode mergeTwoLists(ListNode L1, ListNode L2) {
        ListNode cur1 = L1;
        ListNode cur2 = L2;
        ListNode result = null;// 结果链表的第一个结点
        ListNode last = null;  // 结果链表的最后一个结点
        //有一条为空,就直接返回另一条
        if (L1 == null) {
            return L2;
        }
        if (L2 == null) {
            return L1;
        }

        while (cur1 != null && cur2 != null) {
            if (cur1._value <= cur2._value) {
                // 1. 让 cur1 可以在运行后执行 原 cur1 的下一个结点
                // 2. 让 cur1 尾插到 [result, last] 链表上
                // 3. 更新 last
                ListNode node = cur1.next;

                // 把 cur1 尾插到 result 上
                //cur1.next = null;
                if (result == null) {
                    // result 链表中没有结点
                    result = cur1;
                } else {
                    // result 链表中有结点
                    last.next = cur1;
                }
                last = cur1;    // 更新最后一个结点记录

                cur1 = node;
            } else {
                ListNode next = cur2.next;

                // 把 cur2 尾插到 result 上
                //cur2.next = null;
                if (result == null) {
                    result = cur2;
                } else {
                    last.next = cur2;
                }
                last = cur2;

                cur2 = next;
            }

        }
       //当其中一条链表走到空时,直接将另一条结点剩下的结点尾插到结果链表中
        if (cur1 != null) {
            last.next = cur1;
        }

        if (cur2 != null) {
            last.next = cur2;
        }

        return result;
    }

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值