判断链表是否为回文 1.使用容器栈来进行,将所有的数据压入栈,在一个一个出栈与链表进行比较,只要不相同就直接return false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public bool isTenet (Node head ){ Stack<int > Contains = new Stack<int >(); Node cur = head; while (cur != null ) { Contains.Push(cur.e); cur = cur.next; } cur = head; while (cur != null ) { if (Contains.Pop() != cur.e) return false ; cur = cur.next; } return true ; }
2.翻转后端链表,使用快慢指针找到中间节点,找到后翻转后半部分的链表,比较后段部分的链表是否和前端部分,最后恢复链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public bool IsPalindrome (Node head ) { if (head == null || head.next == null ) return true ; Node slow = head; Node fast = head; while (fast.next != null && fast.next.next != null ) { slow = slow.next; fast = fast.next.next; } fast = slow.next; slow.next = null ; Node cur = null ; while (fast != null ) { cur = fast.next; fast.next = slow; slow = fast; fast = cur; } fast = head; Node tail = slow; bool res = true ; while (slow != null ) { if (fast.val != slow.val) { res = false ; break ; } fast = fast.next; slow = slow.next; } slow = tail; cur = null ; while (slow != null ) { fast = slow.next; slow.next = cur; cur = slow; slow = fast; } return res; }
链表分区 链表分区算法,将链表根据给定值 N 划分为三个部分:小于 N 的节点、等于 N 的节点和大于 N 的节点,同时保持每个分区内节点的原始相对顺序。
Node cur = null; —— 临时存储当前节点的下一个节点。
SmallS 和 SmallE —— 分别指向“小于 N”分区的头节点和尾节点。
MidS 和 MidE —— 分别指向“等于 N”分区的头节点和尾节点。
MoreS 和 MoreE —— 分别指向“大于 N”分区的头节点和尾节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public Node R (Node head,int N ) { Node cur = null ; Node SmallS = null ; Node SmallE = null ; Node MidS = null ; Node MidE = null ; Node MoreS = null ; Node MoreE = null ; while (head != null ) { cur = head.next; head.next = null ; if (head.e < N) { if (SmallS == null ) { SmallS = head; SmallE = head; } else { SmallE.next = head; SmallE = head; } } else if (head.e == N) { if (MidS == null ) { MidS = head; MidE = head; } else { MidE.next = head; MidE = head; } } else { if (MoreS == null ) { MoreS = head; MoreE = head; } else { MoreE.next = head; MoreE = head; } } head = cur; } if (SmallE != null ) { SmallE.next = MidS; MidE = MidE == null ? SmallE : MidE; } if (MidE != null ) { MidE.next = MoreS; } return SmallS != null ? SmallS : (MidS != null ? MidS : MoreS); }
复制带随机指针的链表 1.使用容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Solution { public Node CopyRandomList (Node head ) { if (head == null ) return null ; Dictionary<Node,Node> NodeDic = new Dictionary<Node,Node>(); Node cur = head; while (cur != null ) { NodeDic.Add(cur, new Node(cur.val)); cur = cur.next; } cur = head; while (cur != null ) { NodeDic[cur].next = cur.next != null ? NodeDic[cur.next] : null ; NodeDic[cur].random = cur.random != null ? NodeDic[cur.random] : null ; cur = cur.next; } return NodeDic[head]; } }
NodeDic[cur].next = NodeDic[cur.next];
让新节点的 next 指向对应的新节点
避免新链表仍然依赖原链表
NodeDic[cur].Rand = NodeDic[cur.Rand];
让新节点的 Rand 指向对应的新节点
确保随机指针正确映射
2.原地复制 + 拆分链表 核心思路
在每个原节点后面插入它的副本 (创建新节点并插入)。
设置 random 指针
:新节点的 random = 原节点 random 的副本(即 cur.next.random = cur.random.next)。
拆分新旧链表 ,恢复原链表结构,并返回新链表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public Node copyListWithRand (Node head ) { if (head == null ) return null ; Node cur = head; while (cur != null ) { Node copy = new Node(cur.e); copy.next = cur.next; cur.next = copy; cur = copy.next; } cur = head; while (cur != null ) { if (cur.Rand != null ) { cur.next.Rand = cur.Rand.next; } cur = cur.next.next; } cur = head; Node newHead = head.next; Node copyCur = newHead; while (cur != null ) { cur.next = cur.next.next; cur = cur.next; if (copyCur.next != null ) { copyCur.next = copyCur.next.next; copyCur = copyCur.next; } } return newHead; }
两个可能有环的单链表的第一个相交节点 给定两个可能有环也可能无环的单链表,头节点head1和head2请实现一个函数,如果两个链表相交,请返回相交的第一个节点。如果不
相交,返回null
【要求]如果两个链表长度之和为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)。
1.2个单链表无环
2.一个链表有环,一个链表无环,不可能相交
3.两个链表都有环,此时有3种情况
2个链表不相交
2个链表的相交节点的相同,且为入环节点
2个链表的相交节点的不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 public Node main (Node head1, Node head2 ){ if (head1 == null || head2 == null ) return null ; Node loop1 = GetLoopNode(head1); Node loop2 = GetLoopNode(head2); if (loop1 != null && loop2 != null ) { return bothLoop(head1,loop1,head2,loop2); } else { return noLoop(head1,head2); } } public Node bothLoop (Node head1,Node loop1,Node head2,Node loop2 ){ if (head1 == null || head2 == null ) return null ; if (loop1 == loop2) { Node cur1 = head1; Node cur2 = head2; int n = 0 ; while (cur1 != null ) { n++; cur1 = cur1.next; } while (cur2 != null ) { n--; cur2 = cur2.next; } cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; n = Math.Abs(n); while (n != 0 ) { cur1 = cur1.next; n--; } while (cur1 != cur2) { cur1 = cur1.next; cur2 = cur2.next; } return cur1; } else { Node cur = loop1.next; while (cur != loop1) { if (cur == loop2) return loop1; cur = cur.next; } } return null ; } public Node noLoop (Node head1,Node head2 ){ if (head1 == null || head2 == null ) return null ; Node cur1 = head1; Node cur2 = head2; int n = 0 ; while (cur1!=null ) { n++; cur1 = cur1.next; } while (cur2 != null ) { n--; cur2 = cur2.next; } n = Math.Abs(n); cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; while (n != 0 ) { cur1 = cur1.next; n--; } while (cur1 != cur2) { cur1 = cur1.next; cur2 = cur2.next; } return cur1; } public Node GetLoopNode (Node head ){ if (head == null ||head.next == null || head.next.next == null ) { return null ; } Node slow = head.next; Node fast = head.next.next; while (fast != null && fast.next != null ) { if (slow == fast) break ; slow = slow.next; fast = fast.next.next; } if (fast == null || fast.next == null ) return null ; fast = head; while (slow!=fast) { slow = slow.next; fast = fast.next; } return slow; }