Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
第一题:移除重复节点
一、题目描述:
编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
示例1:
输入:[1, 2, 3, 3, 2, 1]
输出:[1, 2, 3]
示例2:
输入:[1, 1, 1, 1, 2]
输出:[1, 2]
提示:
链表长度在[0, 20000]范围内。 链表元素在[0, 20000]范围内。
二、思路分析:
从这道题开始,就开始链表结构的算法题了,这道题要求我们将链表中重复的节点,只保留第一次出现的节点,是一道典型的去重问题和链表的next指针问题。
我们可以选择使用一个HashSet去记录遍历的链表值,将节点值添加到set中,如果添加失败,说明值已经出现过就把该节点“删掉”,删掉链表的结点只需要将前一个节点的指针指向该节点的下一个节点即可。
三、AC 代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeDuplicateNodes(ListNode head) {
if(head == null) return head;
HashSet<Integer> set = new HashSet<>();
set.add(head.val);
ListNode res = head;
while(head!=null && head.next != null){
if(set.add(head.next.val)){
head = head.next;
}else{
head.next=head.next.next;
}
}
return res;
}
}
第二题:返回倒数第 k 个节点
一、题目描述:
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
示例:
输入: 1->2->3->4->5 和 k = 2
输出: 4
说明:
给定的 k 保证是有效的。
二、思路分析:
本题我的思路是使用栈,先将所有节点入栈,然后要取倒数第几个,我就只需要从栈里弹出k-1个就可以了,然后取栈顶元素。
class Solution {
public int kthToLast(ListNode head, int k) {
Stack<ListNode> stack = new Stack<>();
stack.push(head);
while(head != null && (head = head.next) != null){
stack.push(head);
}
while(--k > 0){
stack.pop();
}
return stack.pop().val;
}
}
然后我提交代码,只超过了6%的提交,于是我又打开题解,看到了快慢指针的解法,只需要一次遍历即可。
一开始先让两个指针都指向头节点,然后先让后指针移动k步,再两个指针一起移动,直到快指针移动到最后一个节点,此时倒数第k个节点就是慢指针的下一个节点。
三、AC 代码:
class Solution {
public int kthToLast(ListNode head, int k) {
ListNode pre = head, cur = head;
for (int i = 0; i < k; i++)
cur = cur.next;
while (cur != null) {
pre = pre.next;
cur = cur.next;
}
return pre.val;
}
}
总结
对于链表的题一定要先知道链表的特性,基本的插入删除和遍历都要熟悉。欢迎大家讨论一起刷题打卡。