您的位置:首页 > 理论基础 > 数据结构算法

数据结构之链表面试题汇总(二)-有序单向链表的合并、单向链表反转

2017-11-02 21:16 811 查看
date: 2016-08-18 9:13:00

title: 数据结构之链表面试题汇总(二)-有序单向链表的合并、单向链表反转

categories: 数据结构

版权声明:本站采用开放的[知识共享署名-非商业性使用-相同方式共享 许可协议]进行许可

所有文章出现的代码,将会出现在我的github中,名字可以根据类全名来找,我在github中的文件夹也会加目录备注。

合并两个有序的单向链表,合并之后的链表依然有序【出现频率高】(剑指offer,题17)

思路:

若两个链表本来有序,在合并的时候,可以参照一下归并排序的归并部分,原理一样。

先比较两条链表的节点,先把小的放进新链表,当其中一条链表到达最后一个节点的时候结束循环

在结束循环后判断那条链表为空,然后直接设置下一个节点为另外一个链表的节点即可,这样就可以把剩下的节点都连接上

图解:













public class MergeList {
public static Node mergeList(Node head1, Node head2) {
// first judge 2 head is null together
if (head1 == null && head2 == null) {
throw new RuntimeException("the 2 of them are null");
}
// judge if one of them is null then return another
if (head1 == null)
return head2;
if (head2 == null)
return head1;

// declare two variables to record the newHead and current pointers
Node newHead;
Node current;

// get the first in the new node
if (head1.getRecord() < head2.getRecord()) {
newHead = head1;
current = head1;
head1 = head1.getNext();
} else {
newHead = head2;
current = head2;
head2 = head2.getNext();
}

// loop that put the less one to the list and update the position while
// one of them is null
while (head1 != null && head2 != null) {
if (head1.getRecord() < head2.getRecord()) {
current.setNext(head1);
current = current.getNext();
head1 = head1.getNext();
} else {
current.setNext(head2);
current = current.getNext();
head2 = head2.getNext();
}
}
// if one of them are null which indicates that the other is not null
// and put
if (head1 == null) {
current.setNext(head2);
}
if (head2 == null) {
current.setNext(head1);
}
// is to the list
// return new list
return newHead;
}

}


测试代码: 第二个链表中的元素都比第一个链表的元素大

public class ReverseLinkedListTest {

public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);

node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);

Node list1 = new Node(7);
Node list2 = new Node(8);
Node list3 = new Node(9);
Node list4 = new Node(10);
list1.setNext(list2);
list2.setNext(list3);
list3.setNext(list4);

RecustionAllElementOfLinkedList.printAllElements(MergeList.mergeList(
node1, list1));
}

}


运行结果:



测试代码二:第二个链表中有与第一个链表相同的元素:

public class ReverseLinkedListTest {

/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);

node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);

Node list1 = new Node(1);
Node list2 = new Node(2);
Node list3 = new Node(6);
Node list4 = new Node(7);
list1.setNext(list2);
list2.setNext(list3);
list3.setNext(list4);

RecustionAllElementOfLinkedList.printAllElements(MergeList.mergeList(
node1, list1));
}

}


运行结果:



单链表的反转【出现频率最高】(剑指offer,题16)

思路:

可以考虑用栈来存放链表中的元素,然后再通过弹栈来存入新链表中来实现该功能,但是这样做不高效

也可以考虑用数组存放链表中的元素,然后通过倒序获取数组中的元素来实现

在这里主要讨论使用递归实现单向链表的反转

首先判断节点是否为空,为空抛异常

接着得到当前节点的下一个节点

把当前节点的下一个节点设置成null

把下一个节点作为参数递归调用,返回的是最后一个节点

把下一个节点的下一个节点设置成当前节点,下一个节点为5 当前节点为4 结果为5.setNext(4)

还有4 3,3 2 ,2 1 完成之后返回递归返回的节点,即新链表的头节点

图解



代码实现:包含使用栈、双指针、递归的方法

public class ReverseLinkedListUtil {
/**
* use stack to reverse single-direction LinkedList
*
* @param head
*            the head of a LinkedList
* @return the new head of a LinkedList
*/
public static Node reverseByStack(Node head) {
Stack<Node> nodes = new Stack<Node>();
if (head == null) {
throw new RuntimeException("the Node is null !");
}
// put all the node to the stack
while (head != null) {
nodes.push(head);
head = head.next;
}
// get all the node in the stack
head = nodes.pop();
Node curNode = head;
while (!nodes.isEmpty()) {

// update the next of the node
Node nextNode = nodes.pop();
nextNode.setNext(null);
curNode.setNext(nextNode);
curNode = nextNode;

}
// return the new head
return head;
}

/**
* use 2 pointers to reverse the single-direction LinkedList
*
* @param head
*            the head of a single-direction LinkedList
* @return the new head of a single-directionLinkedList
*/
public static Node reverseByPointer(Node head) {
// define the previous node to record the previous node
Node previous = null;
// judge that the current node is null
while (head != null) {
// if true move the 2 pointers backward
// get the next node and record it
Node next = head.getNext();
// set the next.next to previous
head.setNext(previous);
// set the previous to current (head)
previous = head;
// set the next to next
head = next;
}
// else break out the loop
return previous;
}

/**
* use recursion to reverse the single-direction LinkedList
*
* @param head
*            the head of the LinkedList
* @return the new-head of the LinkedList that has been reversed
*/
public static Node reverseByRecur(Node head) {
// if the tail is reached return it
if (head == null || head.next == null)
return head;
// get the next node
Node nextNode = head.getNext();
// set the current node's next node to null
head.setNext(null);
// recursion
Node recursionResult = reverseByRecur(nextNode);
// set the next node's next node to current
nextNode.setNext(head);
// return the value that was returned from the recursion
return recursionResult;
}

}


测试代码:

public class ReverseLinkedListTest {

/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);

RecustionAllElementOfLinkedList.printAllElements(ReverseLinkedListUtil
.reverseByRecur(node1));
}

}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息