蚂蚁0915算法岗笔试题解
T1:一个整数x,小红小紫每次可以选择x的一个因子k(要求k为素数)。小红先手,谁先不能操作谁输,问谁赢谁输?
思路:求x的所有质因子个数
import math def divide(n): res = 0 for i in range(2, int(math.sqrt(n))+1): while n % i == 0: res += 1 n = n // i if n > 1: res += 1 return res x = int(input()) ans = divide(x) if ans % 2: print('xiaohong') else: print('xiaozi')
T2:给定一个长度为n的数组,对于每个k,k∈[1, n],求有多少个长度为k的连续上升子数组?
eg:2 3 4 4 2, 长度为1的有[2], [3],...,[2]共5个,长度为2的有[2,3], [3,4]共2个,长度为3的有[2,3,4]共1个,没有长度为4和为5的。返回[5,2,1,0,0]
思路:dp求出以每个元素为结尾的最长连续上升子数组长度l。那么长度为 [1, l ] 的子数组个数都要+1。得到所有长度集合后,用双指针+dp的技巧计算长度数组可以将o(n^2)复杂度降为o(nlogn)。
from collections import Counter n = int(input()) nums = list(map(int, input().split())) ans = [0]*n dp = [1]*n for i in range(1, len(nums)): if nums[i] > nums[i-1]: dp[i] += dp[i-1] count = Counter(dp) count = sorted([(k,v) for k,v in count.items()], reverse=True) ans = [0]*(n+1) i, j = 0, n while i < len(count) and j >= 0: while j >= count[i][0]: j -= 1 ans[j] = ans[j+1] + count[i][1] i += 1 print(' '.join(map(str, ans[:-1])))
T3:定义字符串中每个字母出现的次数是偶数为好串,问对于一个字符串,有多少子序列是好串(子序列可以不连续)?
eg:"ababa"有"aa"4个,"bb"1个,"abab"1个,"abba"1个,"baba"1个
思路:统计字符串中的各字母数,然后排列组合算所有可能数。例如a有5个,那么可以选择4个a,2个啊,0个a,对应是C54+C52+C50的总可能数,其他字母也一样,然后相乘就行。
拓展:可以思考一下如果子串为连续串的做法,状态前缀+动态哈希能搞定[之前微软笔试碰到过]
from collections import Counter from functools import reduce import math MOD = 10**9+7 strings = input() scount = Counter(strings) cntlist = [v for k, v in scount.items()] computelist = [] for cnt in cntlist: p = cnt if cnt % 2: p -= 1 comp = 0 for i in range(p, -1, -2): comp += math.comb(cnt, i) ## compute C cnt i computelist.append(comp) ans = (reduce((lambda x, y: x*y), computelist) - 1) % MOD print(ans)