没通知就降公积金的脉脉,面试考什么?

写在前面

又一家神奇公司映入眼帘:

怎么说呢?自家的瓜出现在自家,至少说明脉脉没有跟微博似的限流。

自家做职场社交,就用自家帖子做全员通知,脉脉你就这么"降本"的吗?🤣

我再找了一下它们的 slogan:

啊?是 ... 是这个意思吗?

作为一个每天都要想更新什么的勤劳型博主,怎能只吃瓜?

我马上去翻看了脉脉的题库,于是有了这篇推文

题目描述

平台:LeetCode

题号:61

给你一个链表的头节点 head,旋转链表,将链表每个节点向右移动 k 个位置。

示例 1:

ini 复制代码
输入:head = [1,2,3,4,5], k = 2

输出:[4,5,1,2,3]

示例 2:

ini 复制代码
输入:head = [0,1,2], k = 4

输出:[2,0,1]

提示:

  • 链表中节点的数目在范围 <math xmlns="http://www.w3.org/1998/Math/MathML"> [ 0 , 500 ] [0, 500] </math>[0,500] 内
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> − 100 < = N o d e . v a l < = 100 -100 <= Node.val <= 100 </math>−100<=Node.val<=100
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 < = k < = 2 ∗ 1 0 9 0 <= k <= 2 * 10^9 </math>0<=k<=2∗109

快慢指针

本质还是道模拟题,分步骤处理即可:

  • 避免不必要的旋转:与链表长度成整数倍的「旋转」都是没有意义的(旋转前后链表不变)
  • 使用「快慢指针」找到倒数第 k 个节点(新头结点),然后完成基本的链接与断开与断开操作

Java 代码:

Java 复制代码
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || k == 0) return head;
        // 计算有效的 k 值:对于与链表长度成整数倍的「旋转」都是没有意义的(旋转前后链表不变)
        int tot = 0;
        ListNode tmp = head;
        while (tmp != null && ++tot > 0) tmp = tmp.next;
        k %= tot;
        if (k == 0) return head;
        // 使用「快慢指针」找到倒数第 k 个节点(新头结点):slow 会停在「新头结点」的「前一位」,也就是「新尾结点」
        ListNode slow = head, fast = head;
        while (k-- > 0) fast = fast.next;
        while (fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }
        // 保存新头结点,并将新尾结点的 next 指针置空
        ListNode nHead = slow.next;
        slow.next = null;
        // 将新链表的前半部分(原链表的后半部分)与原链表的头结点链接上
        fast.next = head;
        return nHead;
    }
}

C++ 代码:

C++ 复制代码
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (head == NULL || k == 0) return head;
        // 计算有效的 k 值:对于与链表长度成整数倍的「旋转」都是没有意义的(旋转前后链表不变)
        int tot = 0;
        ListNode* tmp = head;
        while (tmp != NULL && ++tot > 0) tmp = tmp->next;
        k %= tot;
        // 使用「快慢指针」找到倒数第 k 个节点(新头结点):slow 会停在「新头结点」的「前一位」,也就是「新尾结点」
        if (k == 0) return head;
        // 使用快慢指针找到倒数第 k 个节点
        ListNode* slow = head;
        ListNode* fast = head;
        while (k-- > 0) fast = fast->next;
        while (fast->next != NULL) {
            slow = slow->next;
            fast = fast->next;
        }
        // 保存新头结点,并将新尾结点的 next 指针置空
        ListNode* nHead = slow->next;
        slow->next = NULL;
        // 将新链表的前半部分(原链表的后半部分)与原链表的头结点链接上
        fast->next = head;
        return nHead;
    }
};

Python 代码:

Python 复制代码
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or k == 0: return head
        # 计算有效的 k 值:对于与链表长度成整数倍的「旋转」都是没有意义的(旋转前后链表不变)
        tot, tmp = 0, head
        while tmp:
            tmp = tmp.next
            tot += 1
        k %= tot
        # 使用「快慢指针」找到倒数第 k 个节点(新头结点):slow 会停在「新头结点」的「前一位」,也就是「新尾结点」
        if k == 0: return head
        # 使用快慢指针找到倒数第 k 个节点
        slow, fast = head, head
        while k > 0:
            fast = fast.next
            k -= 1
        while fast.next:
            slow = slow.next
            fast = fast.next
        # 保存新头结点,并将新尾结点的 next 指针置空
        nHead = slow.next
        slow.next = None
        # 将新链表的前半部分(原链表的后半部分)与原链表的头结点链接上
        fast.next = head
        return nHead

TypeScript 代码:

TypeScript 复制代码
function rotateRight(head: ListNode | null, k: number): ListNode | null {
    if (head == null || k == 0) return head;
    // 计算有效的 k 值:对于与链表长度成整数倍的「旋转」都是没有意义的(旋转前后链表不变)
    let tot = 0, tmp = head;
    while (tmp !== null && ++tot > 0) tmp = tmp.next;
    k %= tot;
    // 使用「快慢指针」找到倒数第 k 个节点(新头结点):slow 会停在「新头结点」的「前一位」,也就是「新尾结点」
    if (k == 0) return head;
    // 使用快慢指针找到倒数第 k 个节点
    let slow = head, fast = head;
    while (k-- > 0) fast = fast.next;
    while (fast.next !== null) {
        slow = slow.next;
        fast = fast.next;
    }
    // 保存新头结点,并将新尾结点的 next 指针置空
    let nHead = slow.next;
    slow.next = null;
    // 将新链表的前半部分(原链表的后半部分)与原链表的头结点链接上
    fast.next = head;
    return nHead;
};
  • 时间复杂度: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n)
  • 空间复杂度: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 1 ) O(1) </math>O(1)

闭合成环

另外一个做法是,先成环,再断开:

  • 找到原链表的最后一个节点,将其与原链表的头结点相连(成环),并统计链表长度,更新有效 k
  • 从原链表的头节点出发,找到需要断开的点,进行断开

Java 代码:

java 复制代码
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || k == 0) return head;
        // 先将链表成环,并记录链表的长度
        // tmp 会记录住原链表最后一位节点
        int tot = 1;
        ListNode tmp = head;
        while (tmp.next != null && ++tot > 0) tmp = tmp.next;
        k %= tot;
        if (k == 0) return head;
        // 正式成环
        tmp.next = head;
        // 从原链表 head 出发,走 tot - k - 1 步,找到「新尾结点」进行断开,并将其下一个节点作为新节点返回
        k = tot - k - 1;
        while (k-- > 0) head = head.next;
        ListNode nHead = head.next;
        head.next = null;
        return nHead;
    }
}

C++ 代码:

C++ 复制代码
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (head == NULL || k == 0) return head;
        // 先将链表成环,并记录链表的长度
        // tmp 会记录住原链表最后一位节点
        int tot = 1;
        ListNode* tmp = head;
        while (tmp->next != NULL && ++tot > 0) tmp = tmp->next;
        k %= tot;
        if (k == 0) return head;
        // 正式成环
        tmp->next = head;
        // 从原链表 head 出发,走 tot - k - 1 步,找到「新尾结点」进行断开,并将其下一个节点作为新节点返回
        k = tot - k - 1;
        while (k-- > 0) head = head->next;
        ListNode* nHead = head->next;
        head->next = NULL;
        return nHead;
    }
};

Python 代码:

Python 复制代码
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or k == 0: return head
        # 先将链表成环,并记录链表的长度
        # tmp 会记录住原链表最后一位节点
        tot, tmp = 1, head
        while tmp.next:
            tmp = tmp.next
            tot += 1
        k %= tot
        if k == 0: return head
        # 正式成环
        tmp.next = head
        # 从原链表 head 出发,走 tot - k - 1 步,找到「新尾结点」进行断开,并将其下一个节点作为新节点返回
        k = tot - k - 1
        while k > 0:
            head = head.next
            k -= 1
        nHead = head.next
        head.next = None
        return nHead

TypeScript 代码:

TypeScript 复制代码
function rotateRight(head: ListNode | null, k: number): ListNode | null {
    if (head == null || k == 0) return head;
    // 先将链表成环,并记录链表的长度
    // tmp 会记录住原链表最后一位节点
    let tot = 1, tmp = head;
    while (tmp.next !== null && ++tot > 0) tmp = tmp.next;
    k %= tot;
    if (k == 0) return head;
    // 正式成环
    tmp.next = head;
    k = tot - k - 1;
    while (k-- > 0) head = head.next;
    let nHead = head.next;
    head.next = null;
    return nHead;
};
  • 时间复杂度: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n)
  • 空间复杂度: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 1 ) O(1) </math>O(1)

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

相关推荐
浏览器爱好者几秒前
如何在AWS上部署一个Web应用?
前端·云计算·aws
xiao-xiang17 分钟前
jenkins-通过api获取所有job及最新build信息
前端·servlet·jenkins
C语言魔术师34 分钟前
【小游戏篇】三子棋游戏
前端·算法·游戏
Channing Lewis1 小时前
flask常见问答题
后端·python·flask
Channing Lewis1 小时前
如何保护 Flask API 的安全性?
后端·python·flask
匹马夕阳2 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js
你熬夜了吗?2 小时前
日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件
前端·vue.js·信息可视化
DogDaoDao7 小时前
leetcode 面试经典 150 题:有效的括号
c++·算法·leetcode·面试··stack·有效的括号
桂月二二8 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
Ai 编码助手9 小时前
在 Go 语言中如何高效地处理集合
开发语言·后端·golang