2020-11-22 映ke笔试题

映客直播-笔试题

(1) 最后剩下的人

该题算是Leetcode 剑指offer.62原题。 题目难度:简单

题目描述:0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

输入: n = 5, m = 3
输出: 3

分析:优先可以想到的是暴力模拟,即循环删除直到列表的长度最后为1。该过程每次都需要进行m次查找位置,并且循环遍历整个列表n次,因此时间复杂度为O(mn)。但是,我们可以这样思考这个问题。对当前列表来说,实际上我们删除的位置是可以计算得到的。问题在于,我们使用无论是pop还是remove方法进行删除后,我们指向列表元素的指针会自动指向下一个元素。但对于整个列表来说,我们每次删除的位置都和题目给定的m有关。容易发现,我们每次删除的位置总是(epoch + m - 1)。值得注意的是,当列表到达尽头后,我们需要回到头进行查找。因此使用该数对len(people)进行求余运算即可。

class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        epoch, people = 0, list(range(n))
        
        while len(people) > 1:
            epoch = (epoch + m - 1) % len(people)
            people.pop(epoch)
        return people[0]

笔试中遇到的实际情况是,列表的元素是从1取的,并且m固定为3。

(2) 能否跳跃到最后一个节点

该题同样是Leetcode原题,坐标:Leetcode.55 跳跃游戏 题目难度:中等

题目描述:给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个位置。

输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。

分析:若我们直接考虑暴力解法,会发现在解决这个问题过程中,我们需要不断考虑当前跳多少格子合适。并且还会陷入这样跳有几种跳法的怪圈。然而题目只要求我们返回bool变量。对于类似给定数组最后输出bool值的情况,其实可以优先考虑贪心算法,若贪心算法搞不定,可以尝试使用动态规划。该题就是典型的可以使用贪心算法解决的题目。我们不妨使用例子中的数组作为示例。容易发现,当我们从第一个点开始起跳,其实只要我们每次都选择最大的值进行跳跃,并且保证在最后到达的位置,我们得到的最终节点的位置大于等于数组长度即可。更简单一点说,我们只要保证我们当前的位置能够达到,并且当前位置加上当前的最大跳数值大于最远跳数,就代表当前路径是可达的。

class Solution:
    def canJump(self, nums) :
        max_i = 0       #初始化当前能到达最远的位置
        for i, jump in enumerate(nums):   #i为当前位置,jump是当前位置的跳数
            if max_i>=i and i+jump>max_i:  #如果当前位置能到达,并且当前位置+跳数>最远位置  
                max_i = i+jump  #更新最远能到达位置
        return max_i>=i

(3) 将链表中奇偶位置的节点聚集在一起

Leetcode.328原题。 题目难度:中等

题目描述:给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。

请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。

输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL

分析:模拟过程,并在链表节点内部进行节点的交换。需要注意的是,我们需要额外的指针指向上个被排序的节点的位置,保证下一个节点能够符合原链表数据情况。

class Solution:
    def oddEvenList(self, head: ListNode) -> ListNode:
        if not head:
            return head
        
        evenHead = head.next
        odd, even = head, evenHead
        while even and even.next:
            odd.next = even.next
            odd = odd.next
            even.next = odd.next
            even = even.next
        odd.next = evenHead
        return head

(4) 合并两个有序数组

题目描述:给定两个有序的数组,将他们合并成一个新的数组,并且新的数组有序。

分析:这个题目吧,要是换成链表,还可以写写。不换成链表的话,还对时间复杂度要求贼低,直接使用sort就行了。

class Soulution:
    def newList(self, nums1, nums2):
        return sort(nums1 + nums2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值