算法链表
hiriki
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
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
| class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(); ListNode cur = dummy;
int flag = 0; while(l1!=null||l2!=null) { int x = l1 != null ? l1.val : 0; int y = l2 != null ? l2.val : 0; int sum = x+y+flag;
flag = sum/10; sum = sum%10;
cur.next = new ListNode(sum); cur = cur.next; if(l1!=null) { l1 = l1.next; } if(l2!=null) { l2 = l2.next; } }
if(flag!=0) { cur.next = new ListNode(flag); }
return dummy.next; } }
|
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2
输入:head = [1,2]
输出:[2,1]
示例 3
输入:head = []
输出:[]
思路草稿
题解
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
|
class Solution { public ListNode reverseList(ListNode head) { ListNode cur = head; ListNode pre = null;
while(cur!=null) { ListNode temp = cur.next; cur.next = pre; pre=cur; cur = temp; }
return pre; } }
|
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1
输入:head = [1,2,2,1]
输出:true
示例 2
输入:head = [1,2]
输出:false
题解
转换链表判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Solution { public boolean isPalindrome(ListNode head) { List<Integer> list = new ArrayList<>(); ListNode cur = head; while(cur!=null) { list.add(cur.val); cur = cur.next; }
int left = 0; int right = list.size() - 1;
while(left<right) { if(list.get(left)!=list.get(right)) { return false; } left++; right--; }
return true; } }
|
快慢指针,分割链表,反转后比较
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
| class Solution { public boolean isPalindrome(ListNode head) { ListNode slow = head; ListNode fast = head;
while(fast.next!=null&&fast.next.next!=null) { slow = slow.next; fast = fast.next.next; }
ListNode half = reverseList(slow.next);
ListNode n1 = head; ListNode n2 = half;
while(n1!=null&&n2!=null) { if(n1.val!=n2.val) { slow.next = reverseList(half); return false; } n1 = n1.next; n2 = n2.next; }
slow.next = reverseList(half);
return true; }
private ListNode reverseList(ListNode head) { ListNode pre = null; ListNode cur = head;
while(cur!=null) { ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; }
return pre; } }
|
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1
输入:head = [1,2,3,4]
输出:[2,1,4,3]
思路草稿
题解
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
|
class Solution { public ListNode swapPairs(ListNode head) { ListNode dummy = new ListNode(); dummy.next = head; ListNode cur = dummy;
while(cur.next!=null&&cur.next.next!=null){ ListNode node1 = cur.next; ListNode node2 = cur.next.next; cur.next = node2; node1.next = node2.next; node2.next = node1; cur = node1; }
return dummy.next; } }
|
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
思路草稿
只需将 fast 指针先移动 n 次,让 fast 与 slow 相差 n 个节点即可,这样就能保证 fast 指针走到尾节点时,slow 位于待删除元素的前一个位置。
题解
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
|
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(0,head); ListNode fast = dummy; ListNode slow = dummy;
for(int i = 0;i<n;i++){ fast = fast.next; }
while(fast.next!=null){ slow = slow.next; fast = fast.next; }
slow.next = slow.next.next;
return dummy.next; } }
|
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
题解
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
| public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode curA = headA; ListNode curB = headB; int lenA = 0, lenB = 0; while (curA != null) { lenA++; curA = curA.next; } while (curB != null) { lenB++; curB = curB.next; } curA = headA; curB = headB; if (lenB > lenA) { int tmpLen = lenA; lenA = lenB; lenB = tmpLen; ListNode tmpNode = curA; curA = curB; curB = tmpNode; } int gap = lenA - lenB; while (gap-- > 0) { curA = curA.next; } while (curA != null) { if (curA == curB) { return curA; } curA = curA.next; curB = curB.next; } return null; }
}
|
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
思路草稿
题解
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 class Solution { public ListNode detectCycle(ListNode head) { ListNode fast = head; ListNode slow = head;
do { if(fast==null||fast.next==null){ return null; }
slow = slow.next; fast = fast.next.next; } while(slow!=fast);
ListNode index1 = head; ListNode index2 = slow;
while(index1!=index2){ index1 = index1.next; index2 = index2.next; }
return index1; } }
|
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 1
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
示例 2
输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]
题解
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
|
class Solution { public ListNode reverseKGroup(ListNode head, int k) { ListNode dummy = new ListNode(0,head);
ListNode pre = dummy; ListNode end = dummy;
while(end.next!=null){ for(int i = 0;i<k&&end!=null;i++){ end = end.next; } if(end==null){ break; } ListNode start = pre.next; ListNode next = end.next; end.next = null; pre.next = reverseList(start); start.next = next; pre = start; end = pre; } return dummy.next; }
private ListNode reverseList(ListNode node){ ListNode pre = null; ListNode cur = node;
while(cur!=null){ ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; }
return pre; } }
|