2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案
2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案
1.题目描述
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
2.解题报告
在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的 \textit{next}next 指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。
例如,在本题中,如果我们要删除节点 yy,我们需要知道节点 yy 的前驱节点 xx,并将 xx 的指针指向 yy 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了哑节点,那么头节点的前驱节点就是哑节点本身,此时我们就只需要考虑通用的情况即可。
这个题目是双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
3.最优答案
c答案
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
//定义两个指针,刚开始分别指向头结点,然后先让一个指针先走n-1步,接着两个指针同时遍历链表,当第一个指针到达链表尾部的时候,第二个指针指向的就是要删除的倒数第n个结点。
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode *fast=head;
    struct ListNode *slow=head;
    for(int i=0;i<n;i++){
        fast=fast->next;
        if(fast==NULL) return head->next;
    }
    while(fast->next !=NULL){
        fast=fast->next;
        slow=slow->next;
    }
    slow->next=slow->next->next;
    return head;
    // struct ListNode *fast=head;
    // struct ListNode *slow=head;
    // int i;
    // for(i=0;i<n;i++)
    // {
    //     fast=fast->next;
    //     if(fast == NULL) return head->next;
    // }
    // while(fast->next != NULL)
    // {
    //     fast=fast->next;
    //     slow=slow->next;
    // }
    // slow->next=slow->next->next;
    // return head;
}
c++答案
 class Solution
 {
 public:
	 ListNode* removeNthFromEnd(ListNode* head, int n)
	 {
		 if (!head->next) return NULL;//空链表
		 ListNode *pre = head, *cur = head;
		 for (int i = 0; i < n; i++)
			 cur = cur->next;
		 if (!cur)
			 return head->next;//cur==NULL,此时n大于链表长度,返回首元素
		 while (cur->next)
		 {
			 cur = cur->next;
			 pre = pre->next;//cur先走了n个长度,领先pre了n个长度;所以当cur走到末尾时,pre刚好指向倒数第n个节点
		 }
		 pre->next = pre->next->next;
		 return head;
	 }
 };
java答案
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode root =head;
        HashMap<Integer,ListNode> map = new HashMap<>();
        int count = 0;
        while(head != null){
            count += 1;
            map.put(count,head);
            head = head.next;
        }
        if(count == 1 || count == n){
            root = root.next;
        }else if(n == 1 && count ==2){
            map.get(count - n ).next = null;
        }else {
            map.get(count - n ).next = map.get(count - n + 2);
        }
        return root;
    }
}
JavaScript答案
/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
    if(head == null || n <= 0) {
        return head;
    }
    var dummy = new ListNode(0);
    dummy.next = head;
    var p = dummy
    var q = dummy
    for(var i = 0; i < n + 1; i++) {
        p = p.next;
    }
    while(p) {
        p = p.next;
        q = q.next
    }
    q.next = q.next.next;
    return dummy.next;
    // var count = 0;
    // var p = head;
    // while(p) {
    //     count++
    //     p = p.next
    // }
    // //顺数第m个
    // var m = count - n + 1;
    // var dummy = new ListNode(0);
    // dummy.next = head;
    // var cur = dummy;
    // for(var i = 1; i < m; i++) {
    //     cur = cur.next;
    // }
    // cur.next = cur.next.next;
    // return dummy.next;
};
c#答案
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode RemoveNthFromEnd(ListNode head, int n) {
        if(head==null)return null;
        var list=new List<ListNode>(){head};
        int i=0;
        while(i<list.Count){
         if(list[i].next!=null)   {
             list.Add(list[i].next);
         }
            i++;
        }
        if(list.Count==1){
            return null;
        }
        else if(list.Count==n){
            return list[1];
        }
        i=list.Count-n;
        if(i>-1){
            if(n==1){
                list[list.Count-2].next=null;
            }
            else if(i-i>=0 && i+1<list.Count)
            list[i-1].next=list[i+1];
        }
        return list[0];
    }
}
python2.x答案
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        dummy = ListNode(0)
        dummy.next = head
        first = second = dummy
        for i in range(n):
            first = first.next
        while first.next:
            first = first.next
            second = second.next
        second.next = second.next.next
        return dummy.next
python3.x答案
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        head2 =[head.val]
        while head.next != None:
            head =head.next
            head2.append(head.val)
        head2.pop(-n)
        return head2
go答案
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    var arr []*ListNode
    arr = append(arr, head)
    for node := head; node.Next != nil; node = node.Next {
        arr = append(arr, node.Next)
    }
    if n == len(arr) {
        head = head.Next
    } else if n == 1 {
        del := arr[len(arr)-2]
        del.Next = nil
    } else {
        del := arr[len(arr)-n]
        deleteNode(del)
    }
    return head
}
func deleteNode(node *ListNode) {
    next := node.Next
    node.Val = next.Val
    node.Next = next.Next
}
4.算法面试宝典小程序
微信搜“算法面试宝典”,内含1000个算法题目的7种语言的top5答案和详细解题报告,无论是校招还是社招,让你算法面试中游刃有余,助力薪酬提升30%。

2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案的更多相关文章
- 2021字节跳动校招秋招算法面试真题解题报告--leetcode206 反转链表,内含7种语言答案
		
206.反转链表 1.题目描述 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1-> ...
 - 【算法训练营day4】LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表II
		
[算法训练营day4]LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表 ...
 - 【剑指Offer面试编程题】题目1517:链表中倒数第k个结点--九度OJ
		
题目描述: 输入一个链表,输出该链表中倒数第k个结点. (hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束. 对于每个测试案例,输入的第一行为两个整数n和k(0< ...
 - 打败算法 —— 删除链表的倒数第n个结点
		
本文参考 出自LeetCode上的题库 -- 删除链表的倒数第n个结点,官方的双指针解法没有完全符合"只遍历一遍链表"的要求,本文给出另一种双指针解法 https://leetco ...
 - 字节跳动Android春招,三轮面试,夺命连环问,心态崩了
		
我是春招参加字节面试的,现在已经入职俩月啦,当时没有及时记录下来拖到现在...我尽量回忆当时的内容希望能帮到大家. 投的部门是深圳字节影像,不得不说这个部门的效率,上午投下午就接到hr的电话约面试时间 ...
 - 2021年最新字节跳动Android面试真题解析
		
概述 时间过得是真TM快,回想自己是16年从学校毕业,现在是出来工作的第五个年头啦.在不同的大小公司都待过,就在前段时间顺利的完成了一次跳槽涨薪,面试了几家公司,最终选择了字节跳动.今特此前来跟大家进 ...
 - 秋招如何抱佛脚?2022最新大厂Java面试真题合集(附答案
		
2022秋招眼看着就要来了,但是离谱的是,很多同学最近才想起来还有秋招这回事,所以纷纷临时抱佛脚,问我有没有什么快速磨枪的方法, 我的回答是:有! 说起来,临阵磨枪没有比背八股文更靠谱的了,很多人对这 ...
 - 数据结构+算法面试100题~~~摘自CSDN
		
数据结构+算法面试100题~~~摘自CSDN,作者July 1.把二元查找树转变成排序的双向链表(树) 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调 ...
 - 面试系列二:精选大数据面试真题JVM专项-附答案详细解析
		
公众号(五分钟学大数据)已推出大数据面试系列文章-五分钟小面试,此系列文章将会深入研究各大厂笔面试真题,并根据笔面试题扩展相关的知识点,助力大家都能够成功入职大厂! 大数据笔面试系列文章分为两种类型: ...
 
随机推荐
- 12、elk的使用(2)
			
12.8.收集日志: 因为logstash安装在从节点上,所以这里收集的主要是从节点上的服务日志: 1.收集系统日志: (1)配置文件: vim /etc/logstash/conf.d/system ...
 - Retrofit使用Kotlin协程发送请求
			
Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用.本文简单介绍一下Retrofit中协程的使用 导入依赖 app的build文件中加入: impleme ...
 - 数据连接池JNDI
			
数据库连接有很多中方式,JDBC数据库的连接方式,前边我们已经介绍过了,而开发中我们经常使用的是DataBaseConnectionPool(数据库连接池,DBCP).数据库连接池到底是什么?它比jd ...
 - mysql中的空值
			
空值,即NULL,在数据库中通过is null 和is not null来查询 陷阱一:空值不一定为空 空值是一个比较特殊的字段.在MySQL数据库中,在不同的情形下,空值往往代表不同的含义.这是My ...
 - XCTF Hello CTF
			
一.查壳 二.拖入ida x86静态分析 shift +F12找到字符串. 发现关键字please input your serial 点击进入 这是我们的主函数,F5反编译一下,看一下逻辑. 这里有 ...
 - XCTF WEB backup
			
不用多说,肯定是扫描后台,目录看看能不能找到备份文件,(可恶我的御剑的字典太菜了,居然爆破不出来),建议大家装御剑高一些的版本,或者用dirsearch来扫描,都是不错的. 这里插个知识点,备份文件常 ...
 - Socket 编程介绍
			
Socket 编程发展 Linux Socket 编程领域,为了处理大量连接请求场景,需要使用非阻塞 I/O 和复用.select.poll 和 epoll 是 Linux API 提供的 I/O 复 ...
 - Linux账号和权限管理(第二回合)
			
一.组账号文件二.添加组账号groupadd三.添加删除组成员gpasswd四.删除组账号groupdel五.查询账号信息finger六.文件/目录的权限和归属七.设置文件和目录的归属chown 一. ...
 - C语言:函数
			
1. int scanf ( char * format [ ,argument, ... ]); 返回被赋值的参数的个数
 - python + pytest基本使用方法(运行测试&测试报告)
			
import pytest# 1.运行名称中包含某字符串的测试用例#名称中含add 的测试用例# 执行: pytest -k add test_assert.py# 2.减少测试的运行冗长# 执行: ...