映客直播-笔试题
(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)