-
(0301)—(数组汇总)
给定两个整数数组A和B。
数组B中存在任意一个数字等于数组A中两个不同索引的数字相加之和,那么返回True, 否则返回False。示例:
输入:
A=[-1,8,3]
B=[3,7,2]
输出:True
解释:因为-1+3=2,2出现在数组B中,-1和3都出现在数组A中
来源:WePay 2020春招OA真题-LintCode1831数组汇总
解题思路:简单题不总结了
程序代码:
class Solution:
"""
@param A: a integer array
@param B: a integer array
@return: return true or false
"""
def ArraySummarization(self, A, B):
# write your code here
arrlen = len(A)
result = []
for i in range(arrlen):
for j in range(i,arrlen):
result.append(A[i]+A[j])
for i in B:
if(i in result):
return True
return False
运行结果:
-
(0302)-(警报器)
一个烟雾警报器会监测len秒内的烟雾值,如果这段时间烟雾值平均值大于k那么警报器会报警。现在给你n个数代表刚开始工作n秒内警报器监测的烟雾值(警报器从第len秒开始判断是否报警),问警报器在这段时间内会报警几次?
注意:
1 <= k <= n <= 100000
1 <= len <= 100000
0 <= num[i] <= 100000 (1 <= i <= n)示例:
输入:n = 8, k = 4, len = 3, num = [2, 2, 2, 2, 5, 5, 5, 8]
输出:2
解释: from T = 3 to T = 8, the average smoke value are 2, 2, 3, 4, 5 and 6. 5 and 6 > k, so the answer is 2.
来源:WePay 2020春招OA真题-LintCode1815警报器
解题思路:
读题的时候废了很长时间,一开始以为是从len秒后的每秒的平均烟雾值,结果发现运行过不去。
最后重新读几遍题才知道,原来是len秒内的平均值
可以使用规定长度的队列概念实现。步骤如下:
首先对于加入len个元素,并求出元素的和,如果大于l*k,则count+=1
然后处理第len到n元素,每加入一个元素,就删除队列的第一个元素。
这样做可以不用重复遍历,减少时间复杂度。
程序代码:
class Solution:
"""
@param n:
@param k:
@param l: is len
@param num: //same as problem
@return: //return long
"""
def solve(self, n, k, l, num):
lim = l*k
count = 0
sum = 0
for i in range(l):
sum +=num[i]
if(sum>lim):
count+=1
for i in range(l,n):
sum = sum +num[i]-num[i-l]
if(sum>lim):
count+=1
return count
运行结果:
-
(0303)-(排名查询)
给一个二维数组scores表示每个学生的各科成绩,求出学生中总成绩排名第K的索引。
示例
输入:[[90, 80, 70], [90, 90, 90], [60, 60, 60]]
输出:0
来源:高盛 2020春招OA真题—1804排名查询
解题思路:没啥好说的,暴力解题
程序代码:
class Solution:
"""
@param scores: two dimensional array
@param K: a integer
@return: return a integer
"""
def takeSecond(self,element):
return element[1]
def FindTheRank(self, scores, K):
# write your code here
result = []
for i in range(len(scores)):
sum = 0
for j in scores[i]:
sum+=j
result.append((i,sum))
result.sort(key=self.takeSecond,reverse=True)
return result[K-1][0]
运行结果:
-
(0304)-(旋转字符串Ⅱ)
给出一个字符串(以字符数组形式给出),一个右偏移和一个左偏移,根据给出的偏移量循环移动字符串。(left offest表示字符串向左的偏移量,right offest表示字符串向右的偏移量,左偏移量和右偏移量计算得到总偏移量,在总偏移量处分成两段字符串并交换位置)。
示例1:
输入:str ="abcdefg", left = 3, right = 1
输出:"cdefgab"
解释:左偏移量为3,右偏移量为1,总的偏移量为向左2,故原字符串向左移动,变为"cdefg" + "ab"。
示例2:
输入:str="abcdefg", left = 0, right = 0
输出:"abcdefg"
解释:左偏移量为0,右偏移量为0,总的偏移量为0,故原字符串不变。
示例3:
输入:str = "abcdefg",left = 1, right = 2
输出:"gabcdef"
解释:左偏移量为1,右偏移量为2,总的偏移量为向右1,故原字符串向右移动,变为"g" + "abcdef"。
来源:高盛 2020春招OA真题-LintCode1790旋转字符串Ⅱ
解题思路:
刚开始时没考虑到|left-right|大于len(str)时的情况,测试的时候发现,并总结出规律:
数值大的可求余,不用多次旋转,例如长度是3,1和4的旋转效果是相同的
程序代码:
class Solution:
"""
@param str: A String
@param left: a left offset
@param right: a right offset
@return: return a rotate string
"""
def RotateString2(self, str, left, right):
# write your code here
if(left==right):
return str
else:
strlen = left-right
strlen = strlen%len(str)
return str[strlen:]+str[:strlen]
运行结果:
-
(0305)-(找数字)
给定n个元素的未排序数组,请查找元素k是否存在于数组中。
在下面的编辑器中完成findnNumber函数,它有2个参数:
1整数数组arr,表示该数组中的元素。
2整数k,表示要在数组中搜索的元素。
该函数必须返回true或false,以指示该元素是否存在于数组中示例:
输入:
arr = [1, 2, 3, 4, 5]
k = 1
输出: true
来源:高盛 2020春招OA真题-LintCode1505找数字
解题思路:使用折半查找方法搜索元素
程序代码:
class Solution:
"""
@param nums: a integer array
@param k: a integer
@return: return true or false denoting if the element is present in the array or not
"""
def findnNumber(self, nums, k):
# write your code here
soretnum = nums.sort()
low = 0
high = len(nums)
while(low<high):
mid = int((high-low)/2)+low
if(nums[mid]==k):
return True
elif(nums[mid]>k):
high = mid-1
else:
low = mid+1
return False
运行结果:
-
(0307)-(矩阵游戏)
两个人在一个矩阵中选数字,每个人都最优的去选择数字,被选过的列就不能再被选了,返回最后两个人的分数差
示例:
输入:
grids:[[1,4,7],[2,5,8],[3,6,9]]
输出:6
解释:每一列的最大值是[3, 6, 9],首先,A选择在第三列的9,因此B不可以再选择第三列的数,然后B选择第二列的6,最后A选择3。你应该返回(3 + 9) - 6 = 6
来源:高盛 2020春招OA真题-1421. 矩阵游戏
解题思路:
- 因为简单,所以没有使用一些算法框架。整个解题思路有以下几个步骤:
- 倒置矩阵列表,将列变为行,将行变为列。
- 返回每个子列表的最大元素,并存入列表中
- 对上一个列表进行排序
- 根据序号的奇偶型,进行相加,求得最终和,并返回差值(偶数是a,奇数是b)
代码:
class Solution:
"""
@param grids: a integer matrix
@return: return the difference between two people at last.
"""
def MatrixGame(self, grids):
# write your code here
map = []
y_len = len(grids)
for i in range(len(grids)):
for j in range(len(grids[i])):
while(len(grids[i])>len(map)):
ele = []
map.append(ele)
map[j].append(grids[i][j])
result = []
for i in map:
max = i[0]
for j in i:
if(j>max):
max = j
result.append(max)
result.sort(reverse=True)
a_sum = 0
b_sum = 0
for i in range(len(result)):
if(i%2==0):
a_sum+=result[i]
else:
b_sum+=result[i]
return a_sum-b_sum
结果截图:
-
(0309)-(子数组的最大平均值关注问题)
给定一个由
n
个整数组成的数组,找到给定长度k
的连续子数组,该子数组具有最大平均值。你需要输出最大平均值。注意:
1 <= k <= n <= 30,000
.
给定数组的元素范围是[-10,000, 10,000]
示例:
输入: nums = [1,12,-5,-6,50,3] and k = 4
输出: 12.75
解释: 最大平均为(12-5-6+50)/4 = 51/4 = 12.75
来源:高盛 2020春招OA真题-868.子数组的最大平均值
解题思路:
和前面的警报器思路是一样的。提取这类题目的几个关键词
平均、最大、连续
处理这类题目,只要数学建模成功就可以了。
这里有个关键 部分,
result = []
for i in range(k,len(nums)):
sum = sum+nums[i]-nums[i-k]
result.append(sum)
想要进行改进成以下方式,直接使用一个变量进行存储,但发现不使用上面的方式,会造成断层
if(nums[i]>nums[i-k]):
sum = sum+nums[i]-nums[i-k]
例如:nums = [4,2,1,3,3],k = 2
- 在0-2之间 sum = nums[0]+nums[1]=6
- 在2-5之间,
i = 2,nums[2]>nums[0]为False
i = 3,nums[3]>nums[1]为true,执行代码块
sum = sum +num[3]-nums[1]=nums[0]+nums[3],出现断层
但最后可以这样处理:
max = sum
for i in range(k,len(nums)):
sum = sum+nums[i]-nums[i-k]
if(sum>max):
max = sum
代码:
class Solution:
"""
@param nums: an array
@param k: an integer
@return: the maximum average value
"""
def findMaxAverage(self, nums, k):
# Write your code here
sum = 0
for i in range(k):
sum +=nums[i]
max = sum
for i in range(k,len(nums)):
sum = sum+nums[i]-nums[i-k]
if(sum>max):
max = sum
return max/k
运行结果:
-
(0311)-(丑数)
设计一个算法,找出只含素因子
2
,3
,5
的第 n 小的数。符合条件的数如:
1, 2, 3, 4, 5, 6, 8, 9, 10, 12...
注意:第1个丑数为1
示例1:
输入:1
输出:1
示例2:
输入:9
输出:10
来源:LintCode-4丑数Ⅱ
解题思路:
可以以堆的思想解决,也有点像是算盘,只不过是一个只有3个档的算盘
首先第1个数可以直接设置为1,然后思路背景有3个堆,所有堆上没有对象
值为2的堆,值为3的堆,值为5的堆
通过对这3个堆进行操作,实现1-n之间所有丑数的遍历
每一次操作都是向这3个堆其中的1个堆添加一个对象,则这个对象的值为堆的值
例如:第一次操作,向这3个堆都进行假设添加对象,有3种可能,取能获得最小值的可能,
即向值为2的堆进行添加1个对象,那么就获得了2,存入列表中
依次类推。
代码:
#the clown of number
class Solution:
"""
@param n: An integer
@return: return a integer as description.
"""
def nthUglyNumber(self, n):
# write your code here
lst = [1 for i in range(n)]
a,b,c=0,0,0
for i in range(1,n):
lst[i]=min(lst[a]*2,lst[b]*3,lst[c]*5)
if(lst[i]==lst[a]*2):
a+=1
if(lst[i]==lst[b]*3):
b+=1
if(lst[i]==lst[c]*5):
c+=1
return lst[-1]
截图:
-
(0313)-(合并排序数组Ⅱ)
合并两个有序升序的整数数组A和B变成一个新的数组。新数组也要有序。
示例1:
输入: A=[1], B=[1]
输出:[1,1]
示例2:
输入: A=[1,2,3,4], B=[2,4,5,6]
输出: [1,2,2,3,4,4,5,6]
来源:LintCode-6合并排序数组
代码:
class Solution:
"""
@param A: sorted integer array A
@param B: sorted integer array B
@return: A new sorted integer array
"""
def mergeSortedArray(self, A, B):
# write your code here
result = []
while(len(A)!=0 and len(B)!=0):
if(A[0]<B[0]):
result.append(A.pop(0))
elif(A[0]>B[0]):
result.append(B.pop(0))
else:
result.append(A.pop(0))
result.append(B.pop(0))
if(len(A)!=0):
for i in A:
result.append(i)
else:
for i in B:
result.append(i)
return result
截图:
-
(0315)-(第k大元素)
在数组中找到第 k 大的元素。
示例:
输入:
n=1
nums = [1,3,4,2]
输出:
4
来源:LintCode-5第k大元素
解题思路:没啥好说的,
对数组进行排序,然后输入指定nums[n-1]即可
代码:
class Solution:
"""
@param n: An integer
@param nums: An array
@return: the Kth largest element
"""
def kthLargestElement(self, n, nums):
# write your code here
nums.sort(reverse=True)
return nums[n-1]
if(__name__=='__main__'):
Solution = Solution()
n = eval(input(""))
getnums = input().split(",")
nums = []
for i in getnums:
nums.append(int(i))
print(Solution.kthLargestElement(n,nums))
-
(0317)-(数组的最长前缀)
给定两个正整数X和Y,以及正整数数组nums。
我们需要找到一个最大的index,使得在nums[0], nums[1], .... , nums[index]中,出现X、Y的次数相等,且至少均出现一次,返回该index。
若不存在这样的index,则返回-1。示例:
输入:
X = 2
Y = 4
nums: [1, 2, 3, 4, 4, 3]
输出: 3
解释: 保证 2 和 4 出现相同次数的最长前缀是: {1, 2, 3, 4},所以你应该返回3。
来源:LintCode-1823数组的最长前缀
解题思路:
首先考虑两个极限情况:
一种情况是条件列表中的元素x和元素y出现的次数一样,则会返回列表的长度
一种情况是条件列表中的不存在元素x或元素y,则会返回-1
正常情况下,元素x和元素y出现的次数不一致,返回元素x和元素y出现次数相同的位置
可以通过设计3个过滤器(条件语句)解决问题,例如上面的示例,则有
例如示例中1,2,3经过后,x_num = 1,y_num = 0 maxindex = 0
当元素4经过后,y_num+=1,y_num = 1,出现了x_num = y_num的情况,maxindex则为当前列表的遍历位置,为3
紧接着第2个元素4经过时,y_num = 2,x_num不变,第3个过滤器不变,maxindex还是为3
依次类推,完成
注意:需要补充上面的极限条件的情况,则完成。
代码:
class Solution:
"""
@param X: a integer
@param Y: a integer
@param nums: a list of integer
@return: return the maximum index of largest prefix
"""
def LongestPrefix(self, X, Y, nums):
# write your code here
x_nums = 0
y_nums = 0
maxindex = -1
for i in range(len(nums)):
if(nums[i]==X):
x_nums+=1
if(nums[i]==Y):
y_nums+=1
if(x_nums==y_nums and x_nums!=0):
maxindex = i
return maxindex
刚开始的时候,走入了一个误区,从最终结果进行回溯解决,以下是代码,最终结果是正确的,但时间和内存占用极大
def balance(nums,x,y):
x_list = []
y_list = []
for i in range(len(nums)):
if(nums[i]==x):
x_list.append(i)
if(nums[i]==y):
y_list.append(i)
return x_list,y_list,nums
def getList(nums,x,y):
while(len(balance(nums,x,y)[0])!=0 and len(balance(nums,x,y)[1])!=0):
x_list = balance(nums,x,y)[0]
y_list = balance(nums,x,y)[1]
nums = balance(nums,x,y)[2]
if(len(x_list)== len(y_list)):
return len(nums)-1
else:
if(x_list[-1]>y_list[-1]):
maxlen = x_list.pop(-1)
else:
maxlen = y_list.pop(-1)
newnums = []
for i in range(maxlen):
newnums.append(nums[i])
nums = newnums
return -1
def main():
# nums = [17,19,17,13,14,12,10,13,15,19,15,16,11,16,11,16,17,19,11,15]
# x = 17
# y = 19
nums = [2, 3, 1]
x = 1
y = 10
lst = getList(nums,x,y)
print(lst)
main()
-
(0319)-(寻找字母)
给定一个字符串
str
,返回字符串中字母顺序最大的而且同时在字符串中出现大写和小写的字母。
如果不存在这样的字母,返回‘~‘。示例:
输入:
“aAbBcD‘
输出:
’B‘
解释:因为C和D没有大小写同时出现,A和B都有大小写,但是B比较大,所以返回B
来源:LintCode-1820寻找字母
解题思路:
这道题使用了ascil编码和字母转换的知识,26个大小写英文字母对应的编码如下:
(python3中可以使用chr()将整形数值转换为字母,使用ord()将字母转换为整形数值)
然后根据对字符串进行排序,获取最大的整形数值,并判断字符串是否存在一个对应的大写字母即可
如果都没有,则返回~
代码:
#0319
def str_list(str):
lowerList = []
capList = []
for i in str:
if(ord(i)>=97):
lowerList.append(ord(i))
else:
capList.append(ord(i))
return capList,lowerList
def getResult(capList,lowerList):
#根据accill编码获取数值最大字母,即小写字母
#先对列表进行排序
sort_list = capList
sort_list.sort(reverse=True)
for i in sort_list:
if(i+32 in lowerList):
return chr(i)
return "~"
def main():
str = "looGVSSPbR"
capList = str_list(str)[0]
lowerList = str_list(str)[1]
str = getResult(capList,lowerList)
print(str)
main()
-
(0321)-(岛屿的个数)(占位)
-
(0323)-(列表扁平化)
给定一个列表,该列表中的每个元素要么是个列表,要么是整数。将其变成一个只包含整数的简单列表。
示例:
输入:
[[1,1],2,[1,1]]
输出:
[1,1,2,1,1]
来源:LintCode-22列表扁平化
解题思路:
有两个思路:
首先是正常的解法,通过递归解决
当遍历主列表的元素是单个元素时,则直接存入列表
当遍历主列表的元素是列表时,使用同一个函数遍历即可
代码如下:
class Solution(object):
# @param nestedList a list, each element in the list
# can be a list or integer, for example [1,2,[1,2]]
# @return {int[]} a list of integer
def flatten(self, nestedList):
result = []
self.getElement(nestedList,result)
return result
def getElement(self, nestedList,result):
# Write your code here
for i in nestedList:
if(isinstance(i,int)):
result.append(i)
else:
self.getElement(i,result)
另外有个特殊的方法,也是投机取巧吧
使用python的强制转换str的函数将列表转换为字符串,再将字符串中的 [ ] 和 , 替换掉即可
代码如下:
class Solution(object):
# @param nestedList a list, each element in the list
# can be a list or integer, for example [1,2,[1,2]]
# @return {int[]} a list of integer
def flatten(self, nestedList):
# Write your code here
strList = str(nestedList)
finalstr = strList.replace("[","").replace("]","").replace(" ","")
finalList = finalstr.split(",")
result = []
for i in finalList:
if(i!=""):
result.append(int(i))
return result
-
(0325)-(背包问题IV)
给出 n 个物品, 以及一个数组,
nums[i]
代表第i个物品的大小, 保证大小均为正数, 正整数target
表示背包的大小, 找到能填满背包的方案数。注意:每一个物品只能使用一次
输入:
target = 7
nums = [1,2,3,3,7]
输出:
2
解释:
两个方案 1+3+3和7
来源:LintCode-563背包问题V
解题思路:
这道题与其它的背包问题最大的区别在于两个条件
填满背包和物品只能使用一次
使用动态规划解决,重点在于求出公式
由于之前有讲,所以不再叙述
代码如下:
#背包问题IV
def printMap(map,list,size):
print(" ",end=":")
sizeList = [i for i in range(size)]
print(sizeList)
for i in range(len(map)):
print(list[i],end=" ")
print(i,end=":")
print(map[i])
def buidmap(list,size):
lenoflist = len(list)
map = []
for i in range(len(list)):
ele = [0 for i in range(size)]
map.append(ele)
#这里不用填充第一行
# for i in range(len(map[0])):
# if(i>=list[0]):
# map[0][i]=list[0]
for i in range(len(map)):
map[i][0]=1
map[0][list[0]]=1
return map
def dynamicprogramming(map,list,size):
for i in range(1,len(list)):
for j in range(1,size):
map[i][j] +=(map[i-1][j-list[i]] if j>=list[i] else 0)
map[i][j] +=map[i-1][j]
return map
def main():
goodsList = [1,2,3,3,7]
size = 7
size +=1
map = buidmap(goodsList,size)
#printMap(map,goodsList,size)
resultmap = dynamicprogramming(map,goodsList,size)
#printMap(resultmap,goodsList,size)
print(resultmap[-1][-1])
main()
-
(0327)-(账户合并)
给定一个帐户列表,每个元素
accounts [i]
是一个字符串列表,其中第一个元素accounts [i] [0]
是账户名称,其余元素是这个帐户的电子邮件。
现在,我们想合并这些帐户。
如果两个帐户有相同的电子邮件地址,则这两个帐户肯定属于同一个人。
请注意,即使两个帐户具有相同的名称,它们也可能属于不同的人,因为两个不同的人可能会使用相同的名称。
一个人可以拥有任意数量的账户,但他的所有帐户肯定具有相同的名称。
合并帐户后,按以下格式返回帐户:每个帐户的第一个元素是名称,其余元素是按字典序排序后的电子邮件。
帐户本身可以按任何顺序返回。输入:
[
["John", "johnsmith@mail.com", "john00@mail.com"],
["John", "johnnybravo@mail.com"],
["John", "johnsmith@mail.com", "john_newyork@mail.com"],
["Mary", "mary@mail.com"]
]
输出:
[
["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'],
["John", "johnnybravo@mail.com"],
["Mary", "mary@mail.com"]
]
解释:
第一个第三个John是同一个人的账户,
因为这两个账户有相同的邮箱:"johnsmith@mail.com". 剩下的两个账户分别是不同的人。
因为他们没有和别的账户有相同的邮箱。
你可以以任意顺序返回结果。
比如:
[
['Mary', 'mary@mail.com'],
['John', 'johnnybravo@mail.com'],
['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']
] 也是可以的。
来源:LintCode-1070账户合并
题目解读:
题目叙述有点多,但是表达的意思很简单
1.账户合并的两个条件,两个账户中用户名和用户对应的邮箱其中必须有一个是相同的
2.最后的结果需要进行字典排序
解题思路:
根据题目解读有两部分,解题也对应有两个模块
模块1.账户合并
下面代码有叙述,另外使用python的集合合并元素以及判断两个列表是否存在相同元素
模块2.字典排序
字典排序,直接使用python的sort函数即可
代码:
#账户合并
#根据名字返回name的位置
#前提:列表中至少有一个相同的名称的元素
def getIndexbyName(nameList,name):
indexList = []
for i in range(len(nameList)):
if(nameList[i]==name):
indexList.append(i)
return indexList
def getkeybysort(element):
return element[1]
def run(userList):
newList = []
#注意,这两个列表是一一对应的
nameList = []
emailList = []
for i in userList:
#首先讲元素列表的第1个元素弹出
username = i.pop(0)
#然后判断这个用户是否存在于新用户列表
#如果存在,则获取相对应的位置
if(username in nameList):
indexList = getIndexbyName(nameList,username)
for index in indexList:
email = emailList[index]#获取对应的邮箱列表
#集合化,使用集合的判断是否存在交集的方法
#如果存在交集
boolValue = True
if (set(emailList[index]).isdisjoint(set(i))==False):
boolValue = False
emailList[index] = list(set(emailList[index]).union(set(i)))
break
#否则,分别讲名称和邮箱存入两个列表中
if(boolValue==True):
nameList.append(username)
emailList.append(i)
#如果不存在,则直接讲名称和邮箱存入两个列表中
else:
nameList.append(username)
emailList.append(i)
#前面程序成功
# print(nameList)
# print(emailList)
#进行字典排序
sortbefore = []
for index in range(len(nameList)):
sortbefore.append((nameList[index],emailList[index]))
sortbefore.sort(key=getkeybysort)
#合并两个列表
result = []
for i in sortbefore:
element = []
element.append(i[0])
for j in i[1]:
element.append(j)
result.append(element)
return result
def main():
userList = [
["John", "johnsmith@mail.com", "john00@mail.com"],
["John", "johnnybravo@mail.com"],
["Mary", "mary@mail.com"],
["John", "johnsmith@mail.com", "john_newyork@mail.com"]
]
result = run(userList)
print(result)
main()
-
(0329)-(缺少的字符串)
给出两个字符串,你需要找到缺少的字符串
注意:
输出时字符串顺序为输入字符串内的顺序
输入 :
str1 = "This is an example",
str2 = "is example"
输出 :
["This", "an"]
来源:LintCode-684缺少的字符串
解题思路:
这里有个关键的地方,就是两个字符串的字符串的个数谁多谁少。
根据题意,那么缺少的字符串肯定出自元素个数最多的字符串
其它都挺简单的。
另外,也可以使用python的集合的差集实现。
代码:
class Solution:
"""
@param str1: a given string
@param str2: another given string
@return: An array of missing string
"""
def missingString(self, str1, str2):
# Write your code here
lst1 = str1.split(" ")
lst2 = str2.split(" ")
lst = []
if(len(lst1)>len(lst2)):
maxlst = lst1
minlst = lst2
else:
maxlst = lst2
minlst = lst1
for i in maxlst:
if(i not in minlst):
lst.append(i)
return lst