每日五题(9.26)
1.删除链表的倒数第 n 个结点
链接:https://leetcode.cn/problems/SLwz0R/
给定一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
思路:遍历两边链表?第一次知道总共多长,第二次找到待删除点,前面的指向后面即可
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//创建一个数值为0,下一个节点为头节点的新节点
ListNode dummy = new ListNode(0, head);
//获取头节点之和的长度
int length = getLength(head);
ListNode cur = dummy;
//cur一直遍历,直至找到目标待删点前一个点
for (int i = 1; i < length - n + 1; ++i) {
cur = cur.next;
}
//cur的下一个变成下下一个,即上图3直接指向5,跳过4
cur.next = cur.next.next;
//头节点
ListNode ans = dummy.next;
return ans;
}
public int getLength(ListNode head) {
int length = 0;
while (head != null) {
++length;
head = head.next;
}
return length;
}
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/SLwz0R/solution/shan-chu-lian-biao-de-dao-shu-di-n-ge-ji-ydte/
来源:力扣(LeetCode)
2.链表中环的入口节点
链接:https://leetcode.cn/problems/c32eOV/
给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
思路:
两种方法:
哈希表和快慢指针
哈希表:我们使用不可重复的哈希表,从头节点遍历链表,直到某处添加失败,此处便是环的入口
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode pos = head;
Set<ListNode> visited = new HashSet<ListNode>();
while (pos != null) {
if (visited.contains(pos)) {
return pos;
} else {
visited.add(pos);
}
pos = pos.next;
}
return null;
}
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/c32eOV/solution/lian-biao-zhong-huan-de-ru-kou-jie-dian-vvofe/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
快慢指针:我们使用两个指针,fast和slow,fast每次走两个节点,slow每次一个节点,当快慢指针相遇,并满足了一定的条件时,该节点就是目标入口节点此方法请查看链接https://leetcode.cn/problems/c32eOV/solution/lian-biao-zhong-huan-de-ru-kou-jie-dian-vvofe/
3.两个链表的第一个重合节点
链接:https://leetcode.cn/problems/3u1WK4/
给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例:
输入: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 个节点。
思路解析:
哈希表,使用哈希表先遍历A链直至最后,再使用此哈希表遍历存储B链,如果有重复,即哈希表存储失败,那么此处节点即为我们所求
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> visited = new HashSet<ListNode>();
ListNode temp = headA;
while (temp != null) {
visited.add(temp);
temp = temp.next;
}
temp = headB;
while (temp != null) {
if (visited.contains(temp)) {
return temp;
}
temp = temp.next;
}
return null;
}
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/3u1WK4/solution/liang-ge-lian-biao-de-di-yi-ge-zhong-he-0msfg/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
4.反转链表
链接:https://leetcode.cn/problems/UHnkqh/
给定单链表的头节点 head
,请反转链表,并返回反转后的链表的头节点。
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
思路解析:
栈:使用栈,后进先出,所以先弹出来的,将会是末尾的,再将末尾的指向下一个弹出来的即可
迭代:我们遍历链表时,创建一个prev用以存储当前节点的前节点,当指向修改完毕之后,将当前节点和前节点都后移一个位置
class Solution {
public ListNode reverseList(ListNode head) {
//存储前一个节点
ListNode prev = null;
//存储当前节点,初始为头节点
ListNode curr = head;
while (curr != null) {
//创建next为当前节点的下一个节点
ListNode next = curr.next;
//当前节点的下一个节点改为前节点
curr.next = prev;
//前节点更新为当前节点
prev = curr;
//当前节点更新为下一个节点
curr = next;
}
return prev;
}
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/UHnkqh/solution/fan-zhuan-lian-biao-by-leetcode-solution-34oi/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
5.链表中的两数相加
链接:https://leetcode.cn/problems/lMSNwu/
给定两个 非空链表 l1和 l2 来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
可以假设除了数字 0 之外,这两个数字都不会以零开头。
输入:l1 = [7,2,4,3], l2 = [5,6,4]
输出:[7,8,0,7]
思路解析:
我们要从链表的末尾进行处理,所以我们可以使用栈来处理。将两个链表所有的元素存入栈中,再从栈中一个一个弹出使用
因为链表的长度可以很长,长到超过java的数据限制,所以我们需要使用传统一点的方式进行操作
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
//创建两个栈
Deque<Integer> stack1 = new ArrayDeque<Integer>();
Deque<Integer> stack2 = new ArrayDeque<Integer>();
//存入数据进链表中
while (l1 != null) {
stack1.push(l1.val);
l1 = l1.next;
}
while (l2 != null) {
stack2.push(l2.val);
l2 = l2.next;
}
int carry = 0;
ListNode ans = null;
while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) {
//取出两个链表的末尾数,如果没有,则为0
int a = stack1.isEmpty() ? 0 : stack1.pop();
int b = stack2.isEmpty() ? 0 : stack2.pop();
//二者相加,carry为进位
int cur = a + b + carry;
carry = cur / 10;
//cur模掉10,剩个位数
cur %= 10;
//存入cur进入节点中
ListNode curnode = new ListNode(cur);
//连接节点
curnode.next = ans;
ans = curnode;
}
return ans;
}
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/lMSNwu/solution/lian-biao-zhong-de-liang-shu-xiang-jia-b-cpk2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。