欢迎使用CSDN-markdown编辑器

简单LinkedList 的java代码实现:
public class LinkedListNode {
public int value;
public LinkedListNode next;

public LinkedListNode(int value) {  
    this.value = value;  
    this.next = null;  
}  

}

public class LinkedList {

public LinkedListNode head;  

/*add an element to the tail*/  
public void add(int v) {  
    if (head == null) {  
        this.head = new LinkedListNode(v);  
    } else {  
        LinkedListNode node = head;  
        while (node.next != null) {  
            node = node.next;  
        }  
        node.next = new LinkedListNode(v);  
    }  
}  

/*remove the element that appear first*/  
public void removeFirst(int v) {  
    /* if to be removed is head node */  
    if (head.value == v) {  
        head = head.next;  
        return;  
    }  

    /* iterate to the end and remove target node */  
    LinkedListNode node = head;  
    while (node.next != null) {  
        if (node.next.value == v) {  
            node.next = node.next.next;  
            return;  
        }  
        node = node.next;  
    }  
}  

public void print() {  
    LinkedListNode node = head;  
    while (node != null) {  
        System.out.print(node.value + " ");  
        node = node.next;  
    }  
    System.out.println();  
}  

}

  1. Write code to remove duplicated element from an unsorted linked list. 从无序链表中删除重复元素

来源 Cracking the Code Interview (2nd Edition) Ch2 Q1.

【解答】:题目已经明确说明是无序列表,对这类面试题,一般最差的复杂度是 O(NlogN),也就是需要一次排序过程,所以给出的答案最好要优于O(NlogN)。

方法一:除去重复元素,首先想到利用hash。将List迭代一遍,每拿出一个元素,放到hashtable里,并判断是否重复,如果重复则从List中删除该元素。这个算法的时间复杂度是O(N),但需要O(N)的空间建立hashtable去存放元素。

java代码:http://pastebin.com/UiqMVxdL 这里的linkedlist使用的是java.util.*中的LinkedList。实际面试中往往需要自己实现一个linkedlist。

方法二:利用runner pointer. 这个技巧也是解答LinkedList Problem的重要技巧之一。迭代当前链表,每次迭代利用一个runner去访问之后的元素,删除重复元素。算是naive approach,时间复杂度O(N^2),空间复杂度O(1)。面试中最先可能想到的应该是这种解答,然后可以优化到第一种方法。

  1. Implement am algorithm to find the kth to last element of a singly linked list. 查找单项链表中,距最后一个元素距离为K的元素。

来源 Cracking the Code Interview (2nd Edition) Ch2 Q2.
【解答】:方法一:如果知道链表的长度N,答案就是从第(N-K)个元素。当然这题也就没有意义了。

方法二:利用chaser-runner。首先让runner先移动K位,这时候chaser从链表头部开始,和runner同时以相同的速度迭代链表,当runner到达链表尾部,chaser恰好距离最后一个元素K的距离。时间复杂度O(N), 空间复杂度O(1)。

java代码:http://pastebin.com/MQczDMvT 这里用到的LinkedList是本文开始时定义的data structure.

  1. Given a circular linked list, implement an algorithm which returns the node at the beginning of the loop. 查找有环链表环的头部。

来源 Cracking the Code Interview (2nd Edition) Ch2 Q6.
【解答】: 这个题算是经典面试题之一,和Binary Tree的BFS遍历一样,都属于看上去满有水平,实际并没有太多难度的题目,如果遇到了不会做人品可是败成啥样了!?

首先第一问一般是判断该链表有没有环,接着问如果有环的话,找出环开始的节点。

如果判断是否有环?–Same technique as the last question. We can use runner pointer to detect if there is a loop. 记得以前在学校里跑1500米的时候,我经常被人套圈…类似的,如果一个链表有环,并且进入环以后,将一直在环里走下去,慢的总是会被快的赶上,套圈。所以我们用两个指针,一个slow runner,一个fast runner,每次slow走1个,fast走2个,如果在某个时刻slow == fast指针,则证明有环。

如何判断环的开始是哪个节点?– 这个问题也很容易想通。当两个指针第一次相遇的时候,他们距离环的开始节点还有K个元素,而这K个元素是进入环之前那段链表元素的个数。怎么证明呢?设想两个runner同时从某个环的同一个点出发,快的runner以2倍于慢的runner速度前进,它们第一次重合一定还是在这个出发点的位置,以后每一次相遇也一定是在这个出发点的位置。So,设想现在进入环前的那一段K个节点,是环的一部分,离环真正的开始节点距离为K,那么两个runner同时出发,第一次碰撞必然还是在距离环开始节点K的位置。所以,第一次碰撞时,随便将任意一个runner回到链表头部,此时两个runner以同一速度前进,当他们再次相遇的节点,就是环的开始节点。

java代码:http://pastebin.com/p35Cwgzv

  1. Implement a function to check if a linked list is a palindrome. 判断链表是不是回文链表。

来源 Cracking the Code Interview (2nd Edition) Ch2 Q7.
【解答】:经典面试题了。回文就是 0–>1–>2–>1–>0 奇数个节点, 或者 0–>1–>2–>2–>1–>0 偶数个节点。
方法一:很自然的想法就是把链表反转,然后对比反转以后的链表和原链表的节点值,并且只要比较反转链表和原链表一办的元素就可以。

方法二:利用runner pointer。很多的题目都可以利用这个方法来解决。Runner pointer和递归是解决链表问题最常用的两个方法。
定义两个指针,slow runner和fast runner,fast以2倍于slow的速度向链表尾部移动。如有奇数个节点:当fast到达链表尾部时,slow恰好到达链表中间。如有偶数个节点:fast第一次为null时,slow恰好完成了一半节点的访问。把slow访问过的节点元素值压入一个stack里。此后slow继续向链表尾部访问,同时stack里的元素开始出栈(奇数个元素的情况下要跳过中间元素),比较两个元素值,一旦出现不等,则不是回文,否则是。该解法的时间复杂度是O(N),因为需要一次迭代,同时需要O(N)的空间用作stack来存放链表元素。

java代码 http://pastebin.com/wZ54iSmq 这里的List是本文开始定义的数据结构。

你可能感兴趣的:(数据结构,link-list)