链表的常见算法题:
解决链表的算法题通常有两种方法:
1、 借助容器(栈、数组、哈希表...)
2、 快慢指针
在要求空间复杂度的情况下,我们会使用快慢指针
1、
- 输入链表头节点,奇数长度返回中点,偶数长度返回上终点
- 输入链表头节点,奇数长度返回中点,偶数长度返回下终点
- 输入链表头节点,奇数长度返回中点前一个,偶数长度返回上终点
- 输入链表头节点,奇数长度返回中点前一个,偶数长度返回下终点
public static Node Mid1(Node head){
if(head == null || head.next == null || head.next.next == null){
return head;
}
Node show = head.next;
Node fast = head.next.next;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
show = show.next;
}
return show;
}
public static Node Mid2(Node head){
if(head == null || head.next == null){
return null;
}
if(head.next.next == null){
return head;
}
Node fast = head.next;
Node show = head.next;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
show = show.next;
}
return show;
}
public static Node Mid3(Node head){
if(head == null || head.next == null || head.next.next == null){
return head;
}
Node fast = head.next.next;
Node show = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
show = show.next;
}
return show;
}
public static Node Mid4(Node head){
if(head == null || head.next == null){
return head;
}
if(head.next.next == null){
return head;
}
Node show = head;
Node fast = head.next;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
show = show.next;
}
return show;
}
2、将单链表按某值划分成左边小,中间相等,右边大的形式。
public static Node sort(Node head,int num){
Node sH = null;
Node sT = null;
Node eH = null;
Node eT = null;
Node mH = null;
Node mT = null;
Node cur = head;
while(cur != null){
if(cur.vaule < num){
if(sH == null){
sH = cur;
sT = cur;
}else{
sT.next = cur;
sT = cur;
}
}
else if(cur.vaule == num){
if(eH == null){
eH = cur;
eT = cur;
}else{
eT.next = cur;
eT = cur;
}
}
else{
if(mH == null){
mH = cur;
mT = cur;
}else{
mT.next = cur;
mT = cur;
}
}
cur = cur.next;
}
if(sT != null){
sT.next = eH;
eT = eT == null ? sT : eT;
}
if(eT != null){
eT.next = mH;
}
if(mH != null) {
mT.next = null;
}
return sH != null ? sH : (eH != null ? eH : mH);
}
3、给定一个单链表的头节点head,请判断该链表是否为回文结构
public static boolean ispalindrome(Node head){
Node mid = Mid1(head);
Node cur = mid.next;
mid.next = null;
Node next = null;
while(cur.next != null){
next = cur.next;
cur.next = mid;
mid = cur;
cur = next;
}
cur.next = mid;
Node head1 = head;
Node head2 = cur;
while(head1 != null && head2 != null){
if(head1.vaule != head2.vaule){
return false;
}
head1 = head1.next;
head2 = head2.next;
}
return true;
}
4、一种特殊的单链表节点类描述如下
class Node1{
int Vaiue;
Node1 Next;
Node1 rand;
Node(int Val){Value = val}
}
rand指针是单链表节点结构中新增的指针,rand可能指向链表中的任意一个节点,也可能指向null
给定一个由Node1节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点
【要求】
时间复杂度O(N),额外空间复杂度O(1)
public static Node1 copyListWithRand1(Node1 head){
HashMap<Node1, Node1> node1Map = new HashMap<>();
Node1 cur = head;
while(cur != null){
Node1 node1 = new Node1(cur.vaule);
node1Map.put(cur,node1);
cur = cur.next;
}
cur = head;
while(cur != null){
Node1 node = node1Map.get(cur);
Node1 next = node1Map.get(cur.next);
Node1 rand = node1Map.get(cur.rand);
node.next = next;
node.rand = rand;
cur = cur.next;
}
return node1Map.get(head);
}
public static Node1 copyListWithRand2(Node1 head){
Node1 cur = head;
while(cur != null){
Node1 node = cur.next;
Node1 node1 = new Node1(cur.vaule);
cur.next = node1;
node1.next = node;
cur = cur.next.next;
}
cur = head;
Node1 curCopy = null;
Node1 next = null;
while(cur != null){
next = cur.next.next;
curCopy = cur.next;
curCopy.rand = cur.rand != null ? cur.rand.next : null;
cur = next;
}
Node1 res = head.next;
cur = head;
while(cur != null){
next = cur.next.next;
curCopy = cur.next;
cur.next = next;
curCopy.next = next != null ? next.next : null;
cur = next;
}
return res;
}
5、给定两个可能有环环可能无环的单链表,头节点head1和head2.
请实现一个函数,如果两个链表相交,请返回相交的第一个节点,如果不相交,返回null
【要求】
如果两个链表长度之和为N,时间复杂度请达到O(N) 额外空间复杂度请达到O(1)
分析:
这题需要两种情况
1、 两条链表都没有环
2、 两天链表都有环,两个有环的链表一定有公共环,同样需要分多种情况
没有相交
两个链表入环的节点是同一个
两个链表入环的节点不是同一个
public static Node getloopNode(Node head){
if(head.next == null || head.next.next == null || head.next.next == null){
return null;
}
Node node1 = head.next;
Node node2 = head.next.next;
while(node1 != node2){
if(node2.next == null || node2.next.next == null){
return null;
}
node2 = node2.next.next;
node1 = node1.next;
}
node2 = head;
while(node1 != node2){
node1 = node1.next;
node2 = node2.next;
}
return node1;
}
public static Node noLoop(Node head1,Node head2){
if(head1 == null || head2.next == null){
return null;
}
Node cur1 = head1;
Node cur2 = head2;
int n = 0;
while(cur1.next != null){
n++;
cur1 = cur1.next;
}
while(cur2.next != null){
n--;
cur2 = cur2.next;
}
if(cur1 != cur2){
return null;
}
cur1 = n > 0 ? head1 : head2;
cur2 = cur1 == head1 ? head2 :head1;
n = Math.abs(n);
while(n != 0){
n--;
cur1 = cur1.next;
}
while(cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}
public static Node BothLoop(Node head1,Node loopNode1,Node head2,Node loopNode2){
Node cur1 = null;
Node cur2 = null;
if(loopNode1 == loopNode2){
cur1 = head1;
cur2 = head2;
int n = 0;
while (cur1 != loopNode1){
n++;
cur1 = cur1.next;
}
while (cur2 != loopNode1){
n--;
cur2 = cur2.next;
}
cur1 = n > 0 ? head1 :head2;
cur2 = cur1 == head1 ? head2 : head1;
n = Math.abs(n);
while (n != 0) {
n--;
cur1 = cur1.next;
}
while(cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}else{
cur1 = loopNode1.next;
while(cur1 != loopNode1){
if(cur1 == loopNode2){
return loopNode1;
}
cur1 = cur1.next;
}
return null;
}
}