1.两个链表的第一个公共子节点
具体方法1:哈希和集合
/**
* 方法:通过集合来辅助查找
*
* @param headA
* @param headB
* @return
*/
public static ListNode findFirstCommonNodeBySet(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet<>();
while (headA != null) {
set.add(headA);
headA = headA.next;
}
while (headB != null) {
if (set.contains(headB))
return headB;
headB = headB.next;
}
return null;
}
注:保存的是节点,判断的是地址相同,不是数值相同。
具体方法2:栈
public static ListNode findFirstCommonNodeByStack(ListNode headA, ListNode headB) {
Stack<ListNode> stackA = new Stack();
Stack<ListNode> stackB = new Stack();
while (headA != null) {
stackA.push(headA);
headA = headA.next;
}
while (headB != null) {
stackB.push(headB);
headB = headB.next;
}
ListNode preNode = null;
while (stackB.size() > 0 && stackA.size() > 0) {
if (stackA.peek() == stackB.peek()) {
preNode = stackA.pop();
stackB.pop();
} else {
break;
}
}
return preNode;
}
注:栈是后进后出,我们要找最后一个相等的地方,是因为最后一组一致的结点是第一个结点。另外一个节点只有一个后继,但是可以被多个结点指向
2.判断链表是否是回文序列
1-2-2-1 true
/**
* 方法2:全部压栈
*
* @param head
* @return
*/
public static boolean isPalindromeByAllStack(ListNode head) {
ListNode temp = head;
Stack<Integer> stack = new Stack();
//把链表节点的值存放到栈中
while (temp != null) {
stack.push(temp.val);
temp = temp.next;
}
//然后再出栈
while (head != null) {
if (head.val != stack.pop()) {
return false;
}
head = head.next;
}
return true;
}
3.合并有序链表
1.合并两个
public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
// write code here
ListNode newHead = new ListNode(-1);
ListNode res = newHead;
while (list1 != null || list2 != null) {
if (list1 != null && list2 != null) {//都不为空的情况
if (list1.val < list2.val) {
newHead.next = list1;
list1 = list1.next;
} else if (list1.val > list2.val) {
newHead.next = list2;
list2 = list2.next;
} else { //相等的情况,分别接两个链
newHead.next = list2;
list2 = list2.next;
newHead = newHead.next;
newHead.next = list1;
list1 = list1.next;
}
newHead = newHead.next;
} else if (list1 != null && list2 == null) {
newHead.next = list1;
list1 = list1.next;
newHead = newHead.next;
} else if (list1 == null && list2 != null) {
newHead.next = list2;
list2 = list2.next;
newHead = newHead.next;
}
}
return res.next;
}
/**
* 方法2:比方法1更加精简的实现方法
*
* @param l1
* @param l2
* @return
*/
public static ListNode mergeTwoListsMoreSimple(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
prev.next = l1;
l1 = l1.next;
} else {
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
// 最多只有一个还未被合并完,直接接上去就行了,这是链表合并比数组合并方便的地方
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}
/**
* 方法3:通过递归方式来实现
*
* @param l1
* @param l2
* @return
*/
public static ListNode mergeTwoListsByRe(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
private static ListNode initLinkedList(int[] array) {
ListNode head = null, cur = null;
for (int i = 0; i < array.length; i++) {
ListNode newNode = new ListNode(array[i]);
newNode.next = null;
if (i == 0) {
head = newNode;
cur = head;
} else {
cur.next = newNode;
cur = newNode;
}
}
return head;
}
2.合并k个
/**
* 合并K个链表
*
* @param lists
* @return
*/
public static ListNode mergeKLists(ListNode[] lists) {
ListNode res = null;
for (ListNode list : lists) {
res = mergeTwoListsMoreSimple(res, list);
}
return res;
}
3.将List1删除一部分并把List2中的插入到List1删除的那部分中
4.双指针
1.寻找中间结点
返回中间节点(如果有两个的话,返回第二个)
慢指针一次走一个,快指针一次走两个,快指针走到结尾慢指针正好走到一半。
public static ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
2.寻找倒数第k个元素
先让快指针走,等两个相差k个距离的时候再一起走。(注意链表长度小于k的情况)
public static ListNode getKthFromEnd(ListNode head, int k) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && k > 0) {
fast = fast.next;
k--;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
3.旋转链表
public static ListNode rotateRight(ListNode head, int k) {
if (head == null || k == 0) {
return head;
}
ListNode temp = head;
ListNode fast = head;
ListNode slow = head;
int len = 0;
while (head != null) {
head = head.next;
len++;
}
if (k % len == 0) {
return temp;
}
while ((k % len) > 0) {
k--;
fast = fast.next;
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
ListNode res = slow.next;
slow.next = null;
fast.next = temp;
return res;
}