• 每日一题 为了工作 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+"	");
    			head = head.next;
    		}
    		System.out.println();
    	}
    }
    

      

     

  • 相关阅读:
    处理不均衡数据 (Imbalanced data)
    过拟合 (Overfitting)
    加速神经网络训练 (Speed Up Training)
    Python3 S.join() 个人笔记
    OpenCV中的图像形态学转换
    OpenCV中的绘图函数
    OpenCV中图像的BGR格式及Img对象的属性说明
    OpenCV中图像的读取,显示与保存
    msyql-02
    jumpserver的快速部署
  • 原文地址:https://www.cnblogs.com/walxt/p/12496900.html
Copyright © 2020-2023  润新知