1.两个链表第一个公共子节点
1.这是一道经典的链表问题:输入两条链表,找出他们的第一个公共节点。
使用集合的方法:
public ListNode findFirstCommonNodeBySet(ListNode headA,ListNode headB){
Set<ListNode> set = new HashSet<>();
while(head != null){
set.add(headA);
headA = head.next;
}
while(headB != null){
if(set.contains(headB))
return headB;
headB = headB.next;
}
return null;
}
使用栈的方法:
import java.util.Stack;
public 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, 1}, {15, 78, 78, 15} , {112} 是回文序列,
{1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列。
public Boolean isPalindrome(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.合并有序链表
public ListNode mergeTwoLists(ListNode list1,ListNode list2){
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;
}
优化:
public LIstNode mergeTwoLists(ListNode list1,ListNode list2){
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while(list != null && list2 != null){
if(list1.val<=list2.val){
prev.next = list1;
list1 = list1.next;
}else{
prev.next = list2;
list2 = list2.next;
}
prev = prev.next;
}
//最多只有一个还未被合并完,直接接上去就行了,这是链表合并比数组合并方便的地方
prev.next = list1 == null ? list2 : list1;
return prehead.next;
}
合并K个链表
先将前两个合并,之后再将后面的逐步合并进来,这样的好处是只要将前两个写清楚就行
public ListNode mergeKLists(ListNode[] lists){
ListNode res = null;
for(ListNoe list:lists){
res = mergeTwoLists(res,list);
}
return res;
}
给你两个链表list1和list2,他们包含的元素分别为n个和m个。请你将list1中下标从a到b的几点删除,并将list2接在被删除的节点的位置。
public List mergeInBetween(ListNode list1,int a,int b,ListNode list2){
ListNode pre1 = list1,post1 = list1,post2=list2;
int i = 0,j = 0;
while(pre1 != null && post1 != null && j<b){
if(i != a-1) {
pre1 = pre1.next;
i++;
}
if(j != b){
post1 = post1.next;
j++;
}
}
post1 = post1.next;
while(post2.next != null){
post2 = post2.next;
}
//链1尾接链2头,链2尾接链1后半部分的头
pre1.next = list2;
post2.next = post1;
return list1;
}