腾讯面试题:反转链表的实现

package com.toulan.linkedlist;


/**
 * @author loltoulan
 * @version 1.0.0
 * @time 2020/4/2 22:23
 * @message
 */
public class SingleLinkedListDemo {
    public static void main(String[] args) {
        HeroNode hero1 = new HeroNode(1,"宋江","及时雨");
        HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟");
        HeroNode hero3 = new HeroNode(3,"吴用","智多星");
        HeroNode hero6 = new HeroNode(6,"林冲","豹子头");

        SingleLinkedList linkedList = new SingleLinkedList();
        linkedList.addByOrder(hero1);
        linkedList.addByOrder(hero2);
        linkedList.addByOrder(hero6);
        linkedList.addByOrder(hero3);
        linkedList.addByOrder(hero3);

        linkedList.showHeroList();
        HeroNode hero67 = new HeroNode(6,"鲁智深","花和尚");
        System.out.println("=====================================================");
        linkedList.updateList(hero67);
        linkedList.showHeroList();
        System.out.println("=====================================================");
        linkedList.showHeroListByNo(3);
        System.out.println("=====================================================");
        linkedList.deleteListByNo(6);
        linkedList.showHeroList();
        System.out.println("=====================================================");
        System.out.println(getLength(linkedList.getHead()));
        System.out.println("=====================================================");
        System.out.println(selectNode(linkedList.getHead(), 1));
        System.out.println(selectNode(linkedList.getHead(), 3));
        System.out.println(selectNode(linkedList.getHead(), 2));
        System.out.println("=====================================================");
        reverseList(linkedList.getHead());
        linkedList.showHeroList();
    }


    /**
     * 腾讯面试题:反转链表
     * @param head 头节点
     */
    public static void reverseList(HeroNode head) {
        if (head.next == null || head.next.next == null) {
            return;
        }

        //定义一个辅助的指针,帮我们遍历原来的链表
        HeroNode cur = head.next;
        HeroNode next = null;
        HeroNode reverseHead = new HeroNode(0, "", "");

        while (cur != null) {
            next = cur.next;
            //将reverse的next赋值给cur.next
            cur.next = reverseHead.next;
            //将cur赋值给反转链表的头部,实现反转的主要算法
            reverseHead.next = cur;
            //将cur后移
            cur = next;
        }
        //将反转链表的头节点,赋值给原链表的头节点,实现反转
        head.next = reverseHead.next;
    }




    /**
     *  面试题:新浪面试题,找到倒数第K个节点并返回
     * @param k 第K个节点
     * @param herd 头节点
     * @return  返回该节点
     *
     */
    public static HeroNode selectNode(HeroNode herd,int k) {
        if (herd.next == null) {
            return null;
        }

        int size = getLength(herd);

        if (k < 0 || k > size) {
            return null;
        }

        HeroNode cur = herd.next;

        for (int i = 0; i < size - k; i++) {
            cur = cur.next;
        }

        return cur;
    }


    /**
     *  面试题:获取当前链表的长度
     * @param head 链表的头节点
     * @return 返回链表的有效长度
     */
    public static int getLength(HeroNode head) {
        if (head.next == null || head.next.next == null) {
            return 0;
        }
        HeroNode cur = head.next;

        int length = 0;

        while (cur.next != null) {
            length++;
            cur = cur.next;
        }
        return length+1;
    }
}

//创建一个类,来管理我们的英雄的增删改查
class SingleLinkedList{

    //初始化一个头节点,因为,我们链表是通过头节点来进行数据的查询删除操作。
    private HeroNode head = new HeroNode(0, "", "");

    public HeroNode getHead() {
        return head;
    }

    //首先,我们需要考虑,添加元素时,我们的指针如何移动,我们的数据如何插入
    //因为我们此方法,是一个简单的链表尾插法,
    //首先,我们需要将链表遍历到尾部,但是我们将链表遍历到尾部的核心是什么,核心是我们的next为null
    //找到该节点之后,我们将这个节点的next指向新的next

    /**
     * 尾插法,添加新的节点
     * @param heroNode
     */
   public void add(HeroNode heroNode) {

       // 首先,由于我们的头节点不能动,所以如果我们想判断我们的下一个节点是否为空,我们需要再定义一个指针
       HeroNode temp = head;

       // 我们通过让temp不断后移,来判断我们下一个节点是否为空
       while (true) {
           if (temp.next == null) {
               break;
           }
           temp = temp.next;
       }
       temp.next = heroNode;
    }

    /**
     * 遍历HeroList
     */
    public void showHeroList(){

        //首先我们判断链表是否为空,如果为空,我们直接返回,
        if (head.next == null) {
            System.out.println("链表为空,请插入数据之后再行遍历");
            return;
        }
        // 因为我们还是那个上面判断过了,所以程序运行到这里说明我们的链表至少有一个为空
        // 所以我们直接将temp直接指向下一个节点,当然,指向头节点也是可以的

        HeroNode temp = head.next;
        while (true) {
            if (temp == null) {
                return;
            }
            System.out.println(temp);
            temp = temp.next;
        }

        /*HeroNode temp = head;
        while (true) {
            if (temp.next == null) {
                return;
            }
            System.out.println(temp.next);
            temp.next = temp.next.next;
        }*/

    }


    /**
     * 按顺序插入
     * @param heroNode
     */
    public void addByOrder(HeroNode heroNode) {

        //由于我们的头节点不能动,所以如果我们想判断我们的下一个节点是否可以插入,我们需要再定义一个指针
        HeroNode temp = head;

        //用户来判断我们当前准备添加的英雄是否已经存在
        boolean flag = false;

        //首先我们需要遍历链表
        while (true) {
            //判断当前指针是否已经走到尾部,尾插法
            if (temp.next == null) {
                break;
            }
            //判断当前添加的英雄的编号是否已经存在
            if (temp.next.no == heroNode.no) {
                flag = true;
                break;
            }
            //判断当前节点的下一个节点的编号是否大于当前我们插入的元素的编号
            if (temp.next.no > heroNode.no) {
                break;
            }
            temp = temp.next;
        }
        //判断flag 的值
        if (flag) {
            System.out.printf("您想添加的英雄编号%d已经存在了,不能继续添加\n", heroNode.no);
        } else {
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    /**
     * 更新操作
     * @param heroNode
     */
    public void updateList(HeroNode heroNode) {
        if (head.next == null) {
            System.out.println("链表为空,请填充链表后再进行修改");
            return;
        }
        HeroNode temp = head.next;
        boolean flag = false;
        while (true) {
            if (temp.no == heroNode.no) {
                flag = true;
                break;
            }
            if (temp == null) {
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.name = heroNode.name;
            temp.nickName = heroNode.nickName;
        } else {
            System.out.println("该链表中不存在你要修改的节点");
        }
    }


    /**
     * 删除指定节点
     * @param no
     */
    public void deleteListByNo(int no) {
        //
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                System.out.println("没有找到您想要删除的节点");
                break;
            }
            if (temp.next.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.printf("没有找到您想要删除的节点%d",no);
        }
    }

    /**
     * 通过no查询节点数据
     * @param no
     */
    public void showHeroListByNo(int no) {
        //判断链表是否为空
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                System.out.println("没有找到您想要查询的节点");
                break;
            }
            if (temp.next.no == no) {
                System.out.println(temp.next);
                break;
            }
            temp = temp.next;
        }
    }
}

//创建HeroNode
class HeroNode{
    //好汉编号
    public int no;
     //好汉姓名
    public String name;
     //好汉昵称
    public String nickName;
     //指向下一节点
    public HeroNode next;

    public HeroNode(int hNo, String hName, String hNickName) {
        this.no = hNo;
        this.name = hName;
        this.nickName = hNickName;
    }

    public HeroNode() {
    }


    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值