Code Interview(3)——LinkedList

本文介绍了链表的基本操作实现,包括添加、删除等,并通过具体示例演示了这些操作的应用。此外,还探讨了链表相关的算法问题,如去除重复元素及链表分区等,分析了单链表和双链表的特点及其对算法的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Before deep explore the algorithm related to linkedlist, I firstly review the basic operation towards a linkedlist as follows.

package com.way.collection.list.linkedlist;

public class Node {

    public Node next=null;
    public int data;

    public Node(int data){
        this.data=data;
    }

    public Node addtotail(int data){
        Node end=new Node(data);
        Node node=this;
        while(node.next!=null){
            node=node.next;
        }
        node.next=end;
        return this;
    }

    public Node addAfter(int data,int index){
        Node add=new Node(data);
        Node node=this;
        while(node!=null){
            if(node.data==index){
                add.next=node.next;
                node.next=add;
                return this;
            }
        }
        return this;
    }

    public Node deleteFirst(int data){
        Node node=this;
        if(node.data==data){
            return this.next;
        }
        while(node!=null){
            if(node.next.data==data){
                node.next=node.next.next;
                return this;
            }
        }
        return this;
    }

    public void traverse(){
        Node node=this;
        while(node!=null){
            System.out.println(node.data);
            node=node.next;
        }
    }


    public static void main(String[] args){
        Node node=new Node(1);
        node.addtotail(2);
        node.addtotail(3);
        node.addtotail(4);

        node.traverse();

        node=node.deleteFirst(2);

        node.traverse();

        node.addAfter(0, 1);

        node.traverse();

        node=node.deleteFirst(1);

        node.traverse();

    }

}

After practicing some algorithm question, I found some tips.

Tips:

1, Be careful about the head address of linkedlist
For any operation that may delete the head node of the linkedlist. We should use the method like this: node=node.deleteFirst(1); Because the reference address will be changed when deleting the head. So I have to refresh the “node” like this. Otherwise it will lead to fault when we delete the head node.
That is also why it is a good habit to define a new object in a linkedlist related function, as Node head=this; Node node=head; “head” is preserved particularly for the first node in linkedlist, while “node” is the pointer for operation.

2,Recursion
Algorithm about linkedlist always use recursions. The complexity will increase rapidly. For example:

Write code to remove duplicates from an unsorted linked list. How would you solve this problem if a temporay buffer is not allowed.

Write code to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x.

Here is the code for above questions:

Remove Duplication:

    public Node removeDuplicate(){
        Node head=this;
        Node node=head;
        /*如果是单节点,直接返回*/
        if(node.next==null){
            return node;
        }

        /*不是单节点,继续进行*/
        //记录头结点数据
        int data=head.data;

        //当节点有后续节点时,向后移动
        while(node.next!=null){  
            node=node.next;
            //如果节点数据等于头结点数据,抛弃头节点,即对第头节点之后的链表,进行查重,递归调用
            if(data==node.data){
                return head.next.removeDuplicate();
            }
        }
        //如果没有与头节点数据重复的节点,检查后续的节点,但头节点保留
        head.next=head.next.removeDuplicate();
        //返回头节点
        return head;
    }

Partition:

In solving this question, I have made a serious mistake.
My original solution is this:

    public Node partition(int index){
        Node head=this;
        if(head.next==null){
            return head;
        }
        if(head.data>=index){
            head=head.addtotail(head.data);
            head=head.next.partition(index);
        }else{
            head.next=head.next.partition(index);
        }

        return head;
    }

I debug it for hours until I realize I made a endless loop. I put each data greater than or equal to x to the tail of the list. Indeed it can partition the linked list but the program will keep rotating the nodes at the list tail. (e.g. Input: 1,5,4,2,3),x=3, the algorithm can get “1,2,3,5,4” after several loop but the “4” and “5” will be swapped again and again, never stop. )
It is possible to define a integer to store the length of the list, and force to quick the circle after limited number of loops. But the algorithm seems ugly. And i cost a lot of memory in JVM stack as it has too many recursions.
The ideal method is like this:

    public Node partition(int index){
        Node less=null;
        Node more=null;
        Node node=this;
        while(node.next!=null){
            if(node.data>=index){
                if(more==null){//判断是否为空,如果为空初始化头节点,如果不为空,向尾部加入
                    more=new Node(node.data);
                }else{
                    more.addtotail(node.data);
                }
            }else{
                if(less==null){
                    less=new Node(node.data);
                }else{
                    less.addtotail(node.data);
                }
            }
            node=node.next;
        }
        return less.addtotail(more);
    }

3, Singly Linked List and Doubly Linked List

In singly linked list, when we want to change the location of a node. We have to do like this:

    public Node deleteFirst(int data){
        Node node=this;
        if(node.data==data){
            return this.next;
        }
        while(node!=null){
            if(node.next.data==data){
                node.next=node.next.next;
                return this;
            }
        }
        return this;
    }

node.next=mode.next.next; It seems like a ridiculous code but I have to do so. Because I can’t get the previous node according to current node. There is no this problem in doubly linked list.

class DoublyLinkedListNode{
    int data;
    DoublyLinkedListNode previous=null;
    DoublyLinkedListNode next=null;
}

As a result, doubly linked list consume more space but it benefit for algorithm which needs many location change, such as sort algorithms.


To be continue……

http://www.cnblogs.com/ITtangtang/p/3948610.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值