题目1:假设两个单向链表在某结点相交后,成为一个新的单向链表。两个链表的头结点是已知的,但是相交的结点未知。也就是说,它们相交之前的结点个数是未知的,并且两个链表的结点数也可能不同。假设链表List1和链表List2在相交之前的结点个数分别为n和m,那么m可能等于或小于n,也可能大于n。找出两个链表的合并点。
思路:
1.先获取两个链表的长度(假设List1的长度为m,List2的长度为n,m > n)
2.计算两个链表的长度差 d = m - n
3.从较长的链表(List1)的表头开始,移动d个结点
4.两个链表同时移动,直至出现两个后继指针的值相等的情况
/**
* 找出两个链表的合并点
* @param list1 链表1
* @param list2 链表2
* @return 合并点
*/
public static ListNode findIntersectingNode (ListNode list1, ListNode list2) {
int m = LinkedList.getLength(list1);
int n = LinkedList.getLength(list2);
int diff = 0 ;
ListNode headOfLongList = null ;
ListNode headOfShortList = null ;
if (m < n) {
diff = n - m;
headOfLongList = list2;
headOfShortList = list1;
} else {
diff = m - n;
headOfLongList = list1;
headOfShortList = list2;
}
for (int i = 0 ; i < diff; i++) {
headOfLongList = headOfLongList.getNext();
}
while (headOfLongList != null && headOfShortList != null ) {
headOfLongList = headOfLongList.getNext();
headOfShortList = headOfShortList.getNext();
if (headOfLongList == headOfShortList) {
return headOfLongList;
}
}
return null ;
}
题目:如何找到链表的中间结点
思路1:
遍历链表,得到链表的长度;定位到第n/2个结点,即中间结点。
/**
* 如何找到链表的中间结点
* @param headNode 链表的头结点
* @return 链表的中间结点
*/
public static ListNode findMiddleNode1 (ListNode headNode) {
int length = LinkedList.getLength(headNode);
ListNode middleNode = LinkedList.getNodeByPosition(headNode, length/2 );
return middleNode;
}
思路2:
使用两个指针fastPtr和slowPtr,两个指针同时从头结点出发,并使fastPtr移动速度是slowPtr移动速度的两倍。当fastPtr移动到链表的尾结点时,slowPtr指向的结点就是中间结点
/**
* 如何找到链表的中间结点
* @param headNode 链表的头结点
* @return 链表的中间结点
*/
public static ListNode findMiddleNode2 (ListNode headNode) {
ListNode fastPtr = headNode;
ListNode slowPtr = headNode;
int i = 0 ;
while (fastPtr.getNext() != null ) {
if (i == 0 ) {
fastPtr = fastPtr.getNext();
i = 1 ;
} else if (i == 1 ) {
fastPtr = fastPtr.getNext();
slowPtr = slowPtr.getNext();
i = 0 ;
}
}
return slowPtr;
}
题目:检查链表的长度是奇数还是偶数
思路1:先获取链表的长度,对链表的长度进行奇偶判断
/**
* 检查链表的长度是奇数还是偶数
* @param headNode 链表的头结点
* @return true 是偶数 false 是奇数
*/
public static boolean isEven1 (ListNode headNode) {
int length = LinkedList.getLength(headNode);
if (length % 2 == 0 ) {
return true ;
}
return false ;
}
思路2:
使指针指向链表的头结点,指针每次移动两个结点。如果最后指针指向null,说明链表长度是偶数;否则就是指向尾结点,长度为奇数。
/**
* 检查链表的长度是奇数还是偶数
* @param headNode 链表的头结点
* @return true 是偶数 false 是奇数
*/
public static boolean isEven2 (ListNode headNode) {
while (headNode != null && headNode.getNext() != null ) {
headNode = headNode.getNext().getNext();
}
if (headNode == null ) {
return true ;
}
return false ;
}
题目:将两个有序链表合并为一个新的有序链表
思路1:先获取两个链表的长度,保持长的链表不动,对短的链表遍历,一个一个的插入的新的链表
/**
* 将两个有序链表合并为一个新的有序链表
* @param list1 有序链表
* @param list2 有序链表
* @return 合并后新的链表
*/
public static ListNode mergeList1 (ListNode list1, ListNode list2) {
if (list1 == null ) {
return list2;
}
if (list2 == null ) {
return list1;
}
int m = LinkedList.getLength(list1);
int n = LinkedList.getLength(list2);
ListNode headOfLongList = null ;
ListNode headOfShortList = null ;
if (m < n) {
headOfLongList = list2;
headOfShortList = list1;
} else {
headOfLongList = list1;
headOfShortList = list2;
}
ListNode newHeadNode = headOfLongList;
ListNode previousNode = null ;
ListNode currentNode = null ;
while (headOfLongList != null && headOfShortList != null ) {
if (headOfLongList.getData() <= headOfShortList.getData()) {
previousNode = headOfLongList;
headOfLongList = headOfLongList.getNext();
continue ;
}
currentNode = headOfShortList;
headOfShortList = currentNode.getNext();
previousNode.setNext(currentNode);
currentNode.setNext(headOfLongList);
}
return newHeadNode;
}
思路2:利用递归实现
/**
* 将两个有序链表合并为一个新的有序链表
* @param list1 有序链表
* @param list2 有序链表
* @return 合并后新的链表
*/
public static ListNode mergeList2 (ListNode list1, ListNode list2) {
ListNode result = null ;
if (list1 == null ) {
return list2;
}
if (list2 == null ) {
return list1;
}
if (list1.getData() <= list2.getData()) {
result = list1;
result.setNext(mergeList2(list1.getNext(), list2));
} else {
result = list2;
result.setNext(mergeList2(list1, list2.getNext()));
}
return result;
}