二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
想: 先想,不急于做题。
这道题让我们干嘛呢?判断输入数值是否在数组中,其实就是一个判断
True or False两个for 循环行不行?理论上只要内存足够就可以啊。但是,如果是这样,面试官有必要规定数组 ?那么我们怎么基于算法做呢?首先观察这个数组,“每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序”,这说明什么?说明最后一列最大,依次往前...
图示:
如果数值A小于最后一列的第一个数,那说明最后一列都不满足,那就往前挪一列;如果数值A大于最后一列第一个数,说明第一行不满足,那就往下挪一行。....
如果在一个二维数组中找到数字7,则返回true,如果没有找到,则返回false。
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
rows = len(array)
cols = len(array[0])
if rows > 0 and cols > 0:
row = 0
col = cols - 1
while row < rows and col >= 0:
if target == array[row][col]:
return True
elif target < array[row][col]:
col -= 1
else:
row += 1
return False旋转数组的最小数字
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
想: 先想,不急于做题
让我们干嘛?找最小值,用python的话,偷个懒,不管数组是否旋转,最小值是不会变的,可能最小值的位置会有变化,那直接min()
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
if len(rotateArray)==0:
return 0
else:
return min(rotateArray)上面的方法,嗯,算是顺风车。那么怎么用算法做呢?旋转之后的数组实际上可以划分为两个排序的字数组,而且前面的字数组的元素大于或者等于后面字数组的元素。最小的元素刚好是这两个字数组的分界线。
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
if len(rotateArray)==0:
return 0
else:
length = len(rotateArray)
for i in range(length-1):
if rotateArray[i]>rotateArray[i+1]:
return rotateArray[i+1]调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变
想: 先想,不急于做题
让我们干嘛呢?奇数在前偶数在后,相对位置不变
那就找两个空列表,第一个空列表装奇数,第二个装偶数,再拼接。
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
lo = []
le = []
for d in array:
if d % 2 == 1:
lo.append(d)
else:
le.append(d)
return lo + le数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
想: 先想,不急于做题
让我们干嘛?找出现次数最多的树,且这个数出现的次数超过数组长度的一半。数组为偶数,一半不用说。数组为奇数,一半是
奇数//2,比如9//2=4
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
length = len(numbers)
if length == 0:
return 0
mid = length//2
for i in range(mid+1):
if numbers.count(numbers[i]) >mid:
return numbers[i]
return 0连续子数组的最大和
题目:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)
想: 先想,不急于做题
仔细读题目,其实已经提示我们了-----连续子向量的最大和
class Solution:
def FindGreatestSumOfSubArray(self, array):
maxList = []
tmp = 0
for a in array:
tmp += a
if tmp > 0:
maxList.append(tmp)
#是否大于0是判断是否连续的关键
else: tmp = 0
if not maxList:
return -1
return max(maxList)把数组排成最小的数
题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
想: 先想,不急于做题
先将整数数组转为字符串数组,然后用比较器实现字符串比较大小。如果有字符串A和B, A + B < B + A,则A在前;反之B在前。最后将字符串数组连接去除返回值左侧的0。
我们可以先思考只有两个数字的情况:
[3,32],可以看出来332>323因此需要把数组改变为[32,3]
知识小小讲堂
如何将数组映射为字符串?
常规做法:
#字符串转数组
str = '1,2,3'
arr = str.split(',')
#结果:
arr:['1','2','3']
#数组转字符串
arr = ['a','b']
str = ','.join(arr)
#结果:
str:'a,b'
a = [1,23,456]
b = ''.join(str(i) for i in a)
#结果:
'123456'还能怎么做呢?注意python3和python2的处理是不一样的。
python3----map
a = [1,23,456]
b = list(map(str,a))
print(b)
#结果:
#['1','23','456']python2----map
a = [1,23,456]
b = (map(str,a))
print(b)
#结果:
#['1','23','456']另外,可能会需要用到匿名函数lambda。lambda语句构建的其实是一个函数对象。匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
li = [11, 22, 33]
sl = [1, 2, 3]
new_list = list(map(lambda a, b: a + b, li, sl))
print(list(new_list))
#结果
#[12,24,36]我们可能还需要比较函数cmp(),但是python3里并没有cmp(),这个函数只在python2里有。在python3里用(a>b)-(a<b)来代替
当然这里我用到了排序
# -*- coding:utf-8 -*-
class Solution:
def PrintMinNumber(self, numbers):
# write code here
if len(numbers)==0:
return None
if len(numbers)==1:
return numbers[0]
#把数组转换为字符串
num = list(map(str,numbers))
#我们用冒泡排序排个序---从小到大
for i in range(len(num)):
for j in range(len(num)-1):
if int(num[j]+num[j+1])>int(num[j+1]+num[j]):
num[j],num[j+1] = num[j+1],num[j]
else:
num[j],num[j+1] = num[j],num[j+1]
final_num = ''.join([i for i in num])
return final_num数组中的逆序对
题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.i = 0
def InversePairs(self, data):
# write code here
length = len(data)
for i in range(length):
for j in range(i+1,length):
if data[i]>data[j]:
self.i +=1
b = self.i%1000000007
return b数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。
# -*- coding:utf-8 -*-
class Solution:
def GetNumberOfK(self, data, k):
# write code here
return data.count(k)数组中重复的数字
题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
# -*- coding:utf-8 -*-
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# write code here
for i in range(len(numbers)):
if numbers.count(numbers[i])>1:
duplication[0] = numbers[i]
return True
return False构建乘积数组
题目:给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。
课堂小小知识
累乘:reduce() 函数会对参数序列中元素进行累积。
匿名函数lambda用法
lambda(a,b: a+b)关键字lambda表示匿名函数,冒号前是参数,可以有多个,用逗号隔开,冒号右边的返回值。
例子:
#举一个简单的例子:
def f(x):
return x**2
print f(4)
#Python中使用lambda的话,写成这样,这样是很节省空间的
g = lambda x : x**2
print g(4)
- 进阶-内置函数----
map()
li = [11, 22, 33]
sl = [1, 2, 3]
new_list = list(map(lambda a, b: a + b, li, sl))- 进阶-内置函数----
reduce()Python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在functools模块里 对于序列内所有元素进行累计(包括累加、累乘)操作
from functools import reduce
li = [11,22,33]
result = reduce(lambda a,b:a+b,li)- 进阶-内置函数----
filter() 对于序列中的元素进行筛选,最终获取符合条件的序列
li = [11,22,33]
new_list = filter(lambda a:a>22,li)
print(list(new_list))
#filter第一个参数为空,将获取原来序列
输出结果:
>>>[33]代码:
# -*- coding:utf-8 -*-
class Solution:
def multiply(self, A):
# write code here
B = []
for i in range(len(A)):
B.append(reduce(lambda x,y:x*y, (A[:i] + A[i+1:])))
return B接下来,我们需要串一遍十大排序算法