建议收藏|四大互联网经典链表笔试题

本文分享了面试中常见的三道技术挑战:1)链表重排,要求在保持单链表结构的基础上调整元素顺序;2)链表求和,处理正反向数位的整数相加;3)反转链表,注意从尾部开始每K个节点逆序。提供详细代码和解题思路,适合提升算法与链表能力。
摘要由CSDN通过智能技术生成

猫哥导读:随着大数据行业的发展,求职的道路上也会略显坎坷,公司对员工的要求也会越来越高,如果你在面试的路上没有碰壁过,只能说你太幸运了,我身边的朋友,基本上都会遇到面试失败的情况,大多数技术牛人都卡在了笔试题上,这也是为什么大厂员工跳槽前喜欢刷LeetCode,因为他们基本的技能都会在日常工作中反复的运用,工作经验也是实打实的大厂经验,唯一可以难倒他们就是算法+数据结构题。

赠语

我见过985学校毕业的大佬他们记忆力都很好,胆大心细,爱学习。

如果你普通二本学,请不要眼高手低,多动手反复练习。

  • 机会都是留给有准备的人的,千万不要想着不准备上战场就能成功.

  • 多看面经,面经就是面试官们的招聘导向,透过阅读大量的面经,你能够感受得到面试官想要找到什么样的人,并且你可以有针对性地去准备.

  • 不断地去面试,如果你这次面试失败了,那一定要好好总结其中的原因,一定要想方设法地从面试官口中套出自己的不足,这样你下次面试成功的概率就会增加.

1、重排链表--阿里巴巴

给定一个单链表 L:L0→L1→…→Ln-1→Ln ,

将其重新排列后变为:L0→Ln→L1→Ln-1→L2→Ln-2→…

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.

示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

class Solution {
public:
    void reorderList(ListNode *head) {
        if (head == nullptr) {
            return;
        }
        vector<ListNode *> vec;
        ListNode *node = head;
        while (node != nullptr) {
            vec.emplace_back(node);
            node = node->next;
        }
        int i = 0, j = vec.size() - 1;
        while (i < j) {
            vec[i]->next = vec[j];
            i++;
            if (i == j) {
                break;
            }
            vec[j]->next = vec[i];
            j--;
        }
        vec[i]->next = nullptr;
    }
};

2、链表求和--快手

给定两个用链表表示的整数,每个节点包含一个数位。

这些数位是反向存放的,也就是个位排在链表首部。

编写函数对这两个整数求和,并用链表形式返回结果。

示例:

输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295

输出:2 -> 1 -> 9,即912

进阶:思考一下,假设这些数位是正向存放的,又该如何解决呢?

示例:

输入:(6 -> 1 -> 7) + (2 -> 9 -> 5),即617 + 295

输出:9 -> 1 -> 2,即912

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //初始进位为0
        int pre = 0;
        //操作数
        ListNode mid = new ListNode(0);
        //返回头节点
        ListNode anws = mid ;
        //当l1和l2都不为null时进入while循环
        while(l1!=null&&l2!=null){
            //操作数赋值
            mid.val = (l1.val+l2.val+pre)%10;
            //更新进位
            pre = (l1.val+l2.val+pre)/10;
            //更新头节点
            l1 = l1.next;
            l2=l2.next;
            //头节点更新后判断是否为空
            if(l1==null){
                //如果l1头节点为空且进位为0,则操作数的next直接为l2剩下的
                if(pre==0) {
                    mid.next = l2;
                    return anws;
                }else {
                    //如果有进位,则递归调用addTwoNumbers方法
                    mid.next = addTwoNumbers(l2,new ListNode(pre));
                    return anws;
                }
            }
            //同上
            if(l2 == null){
                if(pre==0) {
                    mid.next = l1;
                    return anws;
                }else {
                    mid.next = addTwoNumbers(l1,new ListNode(pre));
                    return anws;
                }
            }
            //l1 l2更新后都不为null,则设置操作数为0 进入下一次while循环
            mid.next =new ListNode(0);
            mid = mid.next;
        }
        //l1为null,直接不能进入上面while循环的情况下,直接返回l2
        if(l1==null){
            return l2;
        }//同上
        else if(l2 ==null){
            return l1;
        }
        return anws;
    }
}

3、反转链表--字节跳动面试题

# 题目

 这其实是一道变形的链表反转题,大致描述如下给定一个单链表的头节点 head,实现一个调整单链表的函数,使得每K个节点之间为一组进行逆序,并且从链表的尾部开始组起,头部剩余节点数量不够一组的不需要逆序。(不能使用队列或者栈作为辅助)

例如:
链表:1->2->3->4->5->6->7->8->null, K = 3。那么 6->7->8,3->4->5,1->2各位一组。调整后:1->2->5->4->3->8->7->6->null。其中 1,2不调整,因为不够一组。

 # 解答

这道题的难点在于,是从链表的尾部开始组起的,而不是从链表的头部,如果是头部的话,那我们还是比较容易做的,因为你可以遍历链表,每遍历 k 个就拆分为一组来逆序。但是从尾部的话就不一样了,因为是单链表,不能往后遍历组起。不过这道题肯定是用递归比较好做

 先做一道类似的反转题

 在做这道题之前,我们不仿先来看看如果从头部开始组起的话,应该怎么做呢?例如:链表:1->2->3->4->5->6->7->8->null, K = 3。调整后:3->2->1->6->5->4->7->8->null。其中 7,8不调整,因为不够一组。

这道题我们可以用递归来实现,假设方法reverseKNode()的功能是将单链表的每K个节点之间逆序(从头部开始组起的哦);reverse()方法的功能是将一个单链表逆序。那么对于下面的这个单链表,其中 K = 3。

 我们把前K个节点与后面的节点分割出来:

 temp指向的剩余的链表,可以说是原问题的一个子问题。我们可以调用reverseKNode()方法将temp指向的链表每K个节点之间进行逆序。再调用reverse()方法把head指向的那3个节点进行逆序

class Node{
      private String val;
      private Node next;
}


public Node reversePart(Node head  , int k){
    Node temp = head;
    for(int index = 1;index < k&&temp!=null;index++){
        temp = temp.next;
    }
    if(temp == null){
        return  head;
    }
    Node rNode = temp.next;
    temp.next = null;
    Node reverseNode = reverse(head);
    Node partNode = reversePart(rNode , k);
    head.next = partNode;
    return reverseNode;
}


public Node reverse(Node head ){
    if(head == null || head.next == null){
       return  head;
    }
    Node p = head;
    Node q = head.next;
    while (q!=null){
        Node tempNode = q.next;
        q.next = p;
        p=q;
        q=tempNode;
    }
    head.next=null;
    return p;
}


public Node main(Node head  , int k){
    Node tempNode1 = reverse(head);
    Node tempNode2 = reversePart(tempNode1 , k);
    return reverse(tempNode2);
}

4、合并两个排序的链表--美团笔试题

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例1:

输入:1->2->4, 1->3->4

输出:1->1->2->3->4->4

限制:

0 <= 链表长度 <= 1000

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dum = new ListNode(0), cur = dum;
        while(l1 != null && l2 != null) {
            if(l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            }
            else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = l1 != null ? l1 : l2;
        return dum.next;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值