新浪面试题:查找单链表中的倒数第k个结点

对于该面试题,首先我们先创建一个单链表实现CRUD操作,由于我之前已写过对应的文章,现在下面附上链接,这里不再赘述。

创建单链表并实现CRUD操作

对于该面试题,我们的思路是:

首先,获取到该单链表的有效数据的总数count,然后定义一个index=0的指针,且需要一个临时结点cur,cur指向当前遍历到的有效数据,通过循环,当index==(count-k)时,此时就可以得到确切位置的结点。详见代码如下:

package com.liu.linkedlist;

/**
 * @author liuweixin
 * @create 2021-09-07 14:46
 */
//新浪面试题:查找单链表中的倒数第k个结点
public class SinaLinkedList {
    private Node1 head = new Node1("", 0);//头结点;

    public static void main(String[] args) {
        SinaLinkedList list = new SinaLinkedList();//创建一个链表
        list.show();
        list.addNode1(new Node1("a", 1));
        list.addNode1(new Node1("b", 2));
        list.addNode1(new Node1("c", 3));
        list.addNode1(new Node1("d", 4));
        list.addNode1(new Node1("e", 5));
        list.show();
        System.out.println("链表中的总数据数为:" + list.getCount());
        int k = 3;
        System.out.println("倒数第" + k + "个数据为:" + list.getReciprocal(k));
    }
    /**
     * 获取单链表中的倒数第k个结点
     *
     * @param k 倒数第K个
     */
    public Node1 getReciprocal(int k) {
        int index = 0;//从正向开始
        if (k > getCount() || k <= 0) {//判断输入的数是否合理,是否在有效数据的个数范围内
            throw new RuntimeException("输入的数有误");
        }
        if (head.next == null) {
            throw new RuntimeException("链表数据为空");
        }
        Node1 cur = head.next;//同样是借助辅助结点,指向第一个数据
        while (true) {
            if (index == (getCount() - k)) {//正向与 总数-倒数相等时即满足条件
                return cur;
            }
            cur = cur.next;//指针后移
            index++;//正向指针后移
        }

    }

    /**
     * 获取链表的总数
     *
     * @return 返回链表的总数
     */
    public int getCount() {
        int count = 0;
        if (head.next == null) {//链表为空返回0
            return 0;
        }
        Node1 cur = head;//创建一个辅助结点
        while (cur.next != null) {//当cur的下一个结点不等于空时,count++,记录总数
            count++;
            cur = cur.next;//向下递换
        }
        return count;
    }
    /**
     * 添加结点
     *
     * @param Node1 要加入的结点
     */
    //对结点的操作放到链表中实现
    public void addNode1(Node1 Node1) {
        if (head.next == null) {
            //只有一个头结点,可以直接把数据加入到链表中
            head.next = Node1;
        } else {
            Node1 cur = head.next;//借助辅助结点去寻找到插入位置的前一个结点
            while (cur.next != null && cur.next.no < Node1.no) {//当cur.next.no>Node1.no时退出循环,此时已找到插入位置的前一个结点。
                //通过循环获取到插入位置的前一个结点
                cur = cur.next;//cur需要下移,才能找到合适的位置
            }
            if (cur.next == null) {//找到链表的最后仍然没有比插入结点的no值大的,直接添加到链表的最后
                cur.next = Node1;
                return;
            }
            //此时cur.next.no>Node1.no,即找到插入位置的前一个结点
            Node1.next = cur.next;//实现结点的传递
            cur.next = Node1;
        }
    }

    /**
     * 删除链表的结点
     *
     * @param no 结点数据的编号
     */
    public void deleteNode1(int no) {
        if (head.next == null) {
            System.out.println("链表为空,无法删除");
        } else {
            Node1 cur = head.next;//借助辅助结点去寻找到插入位置的前一个结点
            while (true) {
                if (cur.next == null) {//找到最后还没有找到删除的位置,说明该链表没有对应结点
                    System.out.println("链表无该节点,无法删除");
                    return;
                }
                if (cur.next.no == no) {
                    //此时已找到删除位置的前一个结点。
                    if (cur.next.next != null) { //删除结点的下一个结点不为空
                        cur.next = cur.next.next;
                    } else {//删除结点的下一个结点为空
                        cur.next = null;
                    }
                    return;//删除完成,结束方法
                }


                cur = cur.next;

            }
        }
    }

    /**
     * 更改结点信息
     *
     * @param Node1 要更改的结点
     */
    public void update(Node1 Node1) {
        if (head.next == null) {
            System.out.println("链表为空,无法更改");
        } else {
            Node1 cur = head;//借助辅助结点去寻找到插入位置的前一个结点
            while (true) {
                if (cur.next == null) {
                    if (cur.no != Node1.no) {
                        //找到最后还没有找到更新的位置,说明该链表没有对应结点
                        System.out.println("链表无该节点,无法更新");
                    }
                    return;
                }
                if (cur.next.no == Node1.no) {
                    //找到要更新的结点的前一个结点
                    if (cur.next.next != null) { //更新结点的下一个结点不为空
                        Node1.next = cur.next.next;
                        cur.next = Node1;//结点的移接
                    } else {//更新的结点是最后一个结点
                        cur.next = Node1;
                    }
                    return;
                }
                cur = cur.next;
            }

        }
    }


    /**
     * 遍历链表数据
     */
    public void show() {
        if (head.next == null) {
            System.out.println("该链表无数据");
            return;
        }
        Node1 cur = head.next;
        while (cur != null) {//注意这里的指针变化,这里的指针指的是当前遍历的结点,而不是遍历结点的前一个结点,这里跟上面添加和删除的临时结点不同
            System.out.println(cur);
            cur = cur.next;
        }
    }
    

}

class Node1 {//定义一个结点对象,每一个对象就是一个结点
    Node1 next;
    String name;
    int no;

    public Node1(String name, int no) {
        this.name = name;
        this.no = no;
    }

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


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值