删除链表的倒数第K个结点

一、要求

给定一个链表,要求删除倒数第K个结点,然后将该结点删除

二、过程分析

2.1、方法一

2.1.1、思路
  1. 首先给一个方法,遍历该链表,返回链表的结点个数;
  2. 然后开始遍历链表,找到K+1的结点;
  3. 将K+1结点直接指向K-1结点;
  4. 返回K结点;
2.1.2、代码
public LinkNode remove(LinkNode node, int k) throws Exception {
        int n = calculate(node); //得出链表节点个数
		//删除的结点如果超出链表的范围,抛出异常
        LinkNode p1 = new LinkNode(0); //定义一个头结点
        if (k > n || k < 1) {
            throw new Exception("删除的结点超出链表范围!");
        }

        p1.setNext(node); //将头结点指向链表
        for (int i = 0; i < n; i++) {

            if (i == (n - k - 1)) { //找到删除结点的前驱结点
                p1 = node;
                LinkNode res = p1.getNext(); //用一个变量保存链表信息
                p1.setNext(p1.getNext().getNext()); //直接更改链表结点的指向,达到删除节点的要求
                return res;
            }
            node = node.getNext();
        }

        return p1.getNext(); //返回删除的结点
    }
	//计算结点的个数
    public int calculate(LinkNode node) {
        int count = 0;

        LinkNode p = node;
        while (p != null) {
            ++count;
            p = p.getNext();
        }

        return count;
    }
总结

这种方法遍历了两遍链表

2.2、方法二

2.2.1、思路
  1. 首先定义两个指针变量 p1,p2;
  2. 然后p1向后遍历;
  3. 当p1遍历K个结点后,p2开始遍历;
  4. 当p1遍历到尾结点时,p2就遍历到删除结点的前驱结点。
2.2.2、代码
 public LinkNode remove(LinkNode node, int k) throws Exception {
        //定义两个指针变量
        LinkNode p1 = node;
        LinkNode p2 = new LinkNode(0);
        p2.setNext(node); //作为头结点,指向链表
        //用来判断p2结点何时可以遍历,
        //同时也能判断删除的结点是否在链表范围内

        int count = 1; 
        
        while(p1 != null) {
            count++;
            p1 = p1.getNext();

            if(count > k) { //如果p1结点遍历到K个结点后,p2结点开始遍历
                p2 = p2.getNext();
            }
        }

        if (k > count - 1 || k < 1) {
            throw new Exception("删除的结点超出链表范围!");
        }
        return p2;
总结

这种方法通过两个指针,巧妙的将删除倒数第K个节点转换为正数第几个结点,这样就不用多遍历一遍得到结点的个数了,而且多设置了一个变量保存了结点个数,用来判断最后K是否在链表范围内。

你可能感兴趣的:(数据结构,算法,Java)