链表习题精讲01

问题一

  • 如何使用一个高效的存储结构来改进双向链表
  • 答:使用LinkedList,即异或链表,此数据结构的ADT如下
public class LinkdedNode{
   int data;
   LinkedNode pridiff;
}

本结构的神奇之处在于它改进了双向列表,不需要再额外的有一个空间,用来单独存储前置节点和后置节点的位置
在这里插入图片描述

  • 具体证明过程如下
    对于任意的链表
    在这里插入图片描述

  • 存在:
    A的next = NULL XOR B
    B的next = A XOR C
    C的next = B XOR D
    证明方法如下,
    已知:在这里插入图片描述
    固存在当我们想要移动 B节点的时候
    如果想要向前移动
    则有(A XOR C)XOR C = A
    如果想要向后移动
    则有 (A XOR C)XOR A = C

  • 疑问:我B要想要向前移动,如何获取C的值呢?

  • 答:这里需要做一步异或,因为我们已经移动到了B因此我们一定知道B的前继节点的地址,因此才可以知道下一个C的地址

java代码实现:
暂无,困于两地址的异或操作

问题二:找到链表的倒数第n个节点

package day04;


/**
 * @author 海绵宝宝
 * @create 2019- 10- 20 17:14
 **/
public class list {
    public static class ListNode{
        private int data;
        //设置私有成员变量 Data
        private ListNode next;
        //设置私有吓一跳的指针
        public ListNode(int data){
            this.data = data;
        }
        public void setData(int data){
            this.data = data;
        }
        public int getData(){
            return this.data;
        }
        public void setNext(ListNode next){
            this.next = next;
        }
        public ListNode getNext(){
            return this.next;
        }
        //以上为简单的增删更新

        int ListLength(){
            int length = 0;
            ListNode currentNode = this;
            while (currentNode!=null){
                currentNode=currentNode.getNext();
                length++;
            }
            return  length;
        }

        ListNode InsertInLinkedList(ListNode headNode,ListNode nodeToInsert,int position){
            if (headNode == null){
                return nodeToInsert;
            }
            if (position==1){
                headNode.setNext(nodeToInsert);
                return headNode;
            }
            else
            {
                ListNode previousNode = headNode;
                int count =0;
                while (count<=position-1){
                    previousNode=previousNode.getNext();
                    count++;
                }
                ListNode currenNode = previousNode.getNext();
                nodeToInsert.setNext(currenNode);
                previousNode.setNext(nodeToInsert);

            }
            return headNode;
        }

        ListNode addlist(int data,ListNode headNode){
            ListNode listNode = new ListNode(data);
            headNode = headNode.InsertInLinkedList(headNode, listNode, listNode.ListLength());
            return headNode;
        }

        ListNode deletelist(ListNode headNode){
            return null;
        }//JAVA中会自动实现这一部分
        ListNode DeleteNodeFromLinkedList(ListNode headNode,int position){
            if (headNode==null)return null;
            if (position<1||position>headNode.ListLength()){
                System.out.println("error,The location you entered is out limit.");
            }
            if (position==1){
                ListNode currentlist = headNode.getNext();
                headNode=null;
                return currentlist;
            }
            else{
                ListNode previousnode = headNode;
                int count = 1;
                while (count<position){
                    previousnode = previousnode.getNext();
                    count++;
                }
                ListNode currentNode = previousnode.getNext();
                previousnode.setNext(currentNode.getNext());
                currentNode = null;

            }
            return headNode;
        }
        public void add(int data){
            ListNode currentNode = new ListNode(data);
            ListNode node = this;
            while (node.getNext()!=null){
                node = node.getNext();
            }
            node.setNext(currentNode);
        }
    }

        public static void PrintList(ListNode headNode){
            while (headNode!=null){
                System.out.print(headNode.getData()+" ");
                headNode= headNode.getNext();
            }
            System.out.println();
        }
    public static void main(String[] args) {
        ListNode listNode = new ListNode(-1);
//        listNode.setData(3);
        for (int i = 0; i < 19; i++) {
            listNode.add(i);
        }
        
        
        
        
        //PrintList(listNode);
    }
}

为了方便各位读者学习,因此直接给出相关的已经实现好的数据结构和部分方法供大家学习

方法一:

//method01
    //a stupid method不是很想实现它...
        public static ListNode Found_n_method_01(ListNode node, int position){
            while (node!=null){
                ListNode temp = node;
                int count = 0;
                while (temp!=null){
                    count++;
                    temp = temp.getNext();
                }
                if (count==position){
                    return node;
                }

                    node = node.getNext();
            }
            System.out.println("not found");
            return null;
        }

答题思路就是,我不断去看从我这个节点到最后的长度是不是N,如果是的话,我们就直接return这个值。
此方法的时间复杂度为O(n^2),空间复杂度为O(1)
a stupid method

方法二

   //Method02
        //a normal method
        public static ListNode Found_n_method_02(ListNode node, int position){
            if (position>node.ListLength()) {
                System.out.println("not found");
                return null;
            }
            int limit = node.ListLength() - position;
            for (int i = 0; i < limit; i++) {
                node = node.getNext();
            }
            return node;
        }

答题思路就是,我们首先遍历一遍整个列表,得到长度,之后在进行移动
此方法的时间复杂度为O(n),空间复杂度为O(1)
这是一种比较简单的做法,但是·,我们能不呢个再次优化他呢

方法三—双指针

在java中其实并没有指针的概念,这里只是简单的借用一下指针的概念方便大家理解

//Method03
        //a great method
        public static ListNode Found_n_method_03(ListNode node, int position){
                ListNode fTemp = node;
                ListNode sTemp = node;
                while (position>1){
                    sTemp = sTemp.getNext();
                    position--;
                }
                while (sTemp.getNext()!=null){
                    sTemp=sTemp.getNext();
                    fTemp=fTemp.getNext();
                }
            return fTemp;

        }

具体思路就是,我首先使用一个指针指向头部,另一个指针和它相差n-1个位置,这样就可以保证,当最后一个指针的getNext()==null之后,头部指针和相差n-1个位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值