每日一题 为了工作 2020 0315 第十三题

/*双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方

便地访问它的前驱结点和后继结点。

下图是双向链表的逻辑结构图,和单链表不同的是,双向链表中每个节点包含两个节点的指针引用,和一个数据域,这两个节点分别指向前一个节点和后一个节点;

双向链表的这种结构比起单链表,其改进之处正在于此,通过对前后节点的引用可以使得在整个链表中,通过给定的值,可以从前或者向后遍历,大大提升了遍历

查询的效率,一定程度上解决了单链表的性能问题,但与此同时,链表的存储开销也增大了,我们熟悉的linkedList,其底层就是这个原理实现的。

 

/**
* 题目:在双链表中删除倒数第K个节点
* 实现函数可以删除双链表中的倒数第K个节点。
* 要求:
* 如果链表长度为N,时间复杂度为O(N),额外空间复杂度达到O(1)。
* 分析:
* 1.如果链表为空或者 K值小于1, 这种情况下, 参数是无效的, 直接返回即可。
* 除此之外, 让链表从头开始走到尾, 每移动一步, 就让 K的值减1。
*
* 链表: 1->2->3, K=4, 链表根本不存在倒数第4个节点
* 走到的节点: 1 -> 2 -> 3
* K变化为: 3 2 1
*
* 链表: 1->2->3, K= 3, 链表倒数第3个节点是l 节点。
* 走到的节点: 1 -> 2 -> 3
* K变化为: 2 I 0
*
* 链表: 1->2->3, K=2, 链表倒数第2个节点是2节点。
* 走到的节点: 1 -> 2 -> 3
* K变化为: 1 0 1
*
* 由以上三种情况可知, 让链表从头开始走到尾, 每移动一步, 就让 K值减 1, 当链表
*走到结尾时, 如果 K值大于0, 说明不用调整链表, 因为链表根本没有倒数第 K个节点,
*此时将原链表直接返回即可;
*
* 如果 K值等于0, 说明链表倒数第K个节点就是头节点, 此时直接返回head.next,
*也就是原链表的第二个节点,让第二个节点作为链表的头返回即可,相当于删除头节点;
*
* 如果K值小于0,首先明确一点, 如果要删除链表的头节点之后的某个节点, 实际上需要
*找到要删除节点的前一个节点, 比如: 1->2->3, 如果想删除节点2, 则需要找到节点1,
*然后把节点1连到节点3上(1->3), 以此来达到删除节点2的目的。
*
* 如果K值小于0, 如何找到要删除节点的前一个节点呢?方法如下:
*1. 重新从头节点开始走, 每移动一步, 就让 K的值加 1。
*2. 当 K等于 0时, 移动停止, 移动到的节点就是要删除节点的前一个节点。
*
* 如果链表长度为N, 要删除倒数第K个节点, 很明显,倒数第K个节点的前一个节点就是
*第 N-K个节点。在第一次遍历后, K的值变为 K-N。第二次遍历时,K的值不断加1,加到 0
*就停止遍历, 第二次遍历当然会停到第 N-K个节点的位置。
*
* 注意:
* 要注意 last指针的重连。
* @author 雪瞳
*
*/

public class DoubleNode {
    public int value;
    public DoubleNode next;
    public DoubleNode last;
    public DoubleNode(int data) {
        this.value=data;
    }
}
public class ReamoNode {
    
    public DoubleNode removeLastKthNode(DoubleNode head , int K) {
        if(K<0 || head == null) {
            return null;
        }
        DoubleNode cur = head;
        while(cur!=null) {
            K = K-1;
            cur = cur.next;
        }
        if(K==0) {
            head = head.next;
            head.last = null;
        }
        if(K<0) {
            cur = head;
            //先自增在判断,如果自增完成后不满足判断条件,说明当前节点cur的下一个节点就是需要删除的节点
            while(++K != 0) {
                cur = cur.next;
            }
            //将当前节点与下一个节点的下一节点相连接
            DoubleNode newNext =cur.next.next;
            cur.next = newNext;
            //若newNext不是空则需要将cur和newNext相连
            if(newNext != null) {
                newNext.last = cur;
            }
        }
        return head;
    }
}
import java.util.Random;
import java.util.Scanner;

public class testRemoveNode {
	public static void main(String[] args) {
		testRemoveNode test = new testRemoveNode();
		ReamoNode remove = new ReamoNode();
		Random rand = new Random();
		DoubleNode nodes[]=new DoubleNode[10];
		Scanner sc = new Scanner(System.in);
		System.out.print("请输入需要删除倒数第几个节点 K=");
		int K = sc.nextInt();
		
		for(int i=0;i<nodes.length;i++) {
			nodes[i]=new DoubleNode(rand.nextInt(10));
		}
		for(int i =0;i<nodes.length-1;i++) {
			nodes[i].next=nodes[i+1];
		}
		
		test.showNode(nodes[0]);
		remove.removeLastKthNode(nodes[0], K);
		test.showNode(nodes[0]);
	}
	public void showNode(DoubleNode head) {
		System.out.println("链表内的元素如下所示...");
		while(head != null) {
			System.out.print(head.value+"\t");
			head = head.next;
		}
		System.out.println();
	}
}

  

 

猜你喜欢

转载自www.cnblogs.com/walxt/p/12496900.html
今日推荐