《剑指Offer》——数组(Python3 实现)

目录

数组

1、二维数组中的查找

2、旋转数组的最小数字

3、调整数组顺序使奇数位于偶数前面

4、数组中出现次数超过一半的数字

5、连续子数组的最大和

6、把数组排成最小的数

变形:把数组排成最大的数。

7、数字在排序数组中出现的次数

8、数组中只出现一次的数字

9、数组中重复的数字

10、构建乘积数组


数组

1、二维数组中的查找

问题:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

思路一

# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    def Find(self, target, array):
        if array==[[]]:  #不能用not array,因为[[]]不为空,它是有一个元素为列表,但列表为空的数组
            return False
        x=len(array[0])-1
        y=len(array)-1
        #从左下角开始遍历
        startX=0
        startY=y
        #循环条件,到右上点结束,因为查找方向为向右或向上
        while startX<=x and startY>=0:
            if array[startX][startY]>target:
                startY-=1
            elif array[startX][startY]<target:
                startX+=1
            else:
                return True
        return False

思路二

# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        rows=len(array)
        cols=len(array[0])
        for i in range(rows):
            for j in range(cols):
                if target==array[i][j]:
                    return True
        return False
if __name__=='__main__':
    answer=Solution()
    arr=[[1,2,3],[7,8,9],[11,12,13]]
    tar=9
    print(answer.Find(tar,arr))

2、旋转数组的最小数字

问题:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

思路:最小值正好位于两段中间,用二分查找(折半查找法)即可。

# -*- coding:utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        start=0
        end=len(rotateArray)-1
        while start<end:
            mid=(start+end)//2
            #中间值<最左边值,由于本身是有两个递增数组组成,所以中间值右边的不需要考虑
            if rotateArray[mid]<rotateArray[start]:
                end=mid
            elif rotateArray[mid]>rotateArray[start]:
                start=mid
            else:
                return rotateArray[mid+1]

3、调整数组顺序使奇数位于偶数前面

问题:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

# -*- coding:utf-8 -*-
class Solution:
    def reOrderArray(self,array):
        if not array:
            return []
        odd=[]
        even=[]
        for i in array:
            if i%2==1:
                odd.append(i)
            else:
                even.append(i)
        return odd+even

4、数组中出现次数超过一半的数字

问题:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

# -*- coding:utf-8 -*-
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        lenth=len(numbers)
        a=set(numbers)
        for i in a:
            if numbers.count(i)>lenth/2:
               return i
        return 0

5、连续子数组的最大和

问题:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

思路

# -*- coding:utf-8 -*-
class Solution:
    def FindGreatestSumOfSubArray(self,array):
        if not array:
            return []
        sum_arr=0
        max_sum=array[0]
        for i in array:
            if sum_arr>0:
                sum_arr+=i
            else:
                sum_arr=i
            max_sum=max(sum_arr,max_sum)
        return max_sum

if __name__=='__main__':
    array=[1,-2,3,10,-4,7,2,-5]
    result=Solution()
    print(result.FindGreatestSumOfSubArray(array))

6、把数组排成最小的数

问题:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

# -*- coding:utf-8 -*-
class Solution:
    def cmp(self,x,y):  #比较左+右,右+左,判断哪个小,然后返回
        s1=str(x)+str(y)
        s2=str(y)+str(x)
        if s1<=s2:
            return s1
        if s1>s2:
            return s2

    def PrintMinNumber(self,numbers):
        if not numbers:
            return ''
        numbers.sort()  #由小到大排序
        #不断替换index为0,1的值为cmp的返回值,直至最后数组中仅剩一个元素
        while len(numbers)>1:
            numbers[0]=self.cmp(numbers[0],numbers[1])
            numbers.remove(numbers[1])
        return numbers[0]

if __name__=='__main__':
    array=[3,32,321]
    result=Solution()
    print(result.PrintMinNumber(array))

变形:把数组排成最大的数。

class Solution:
    def cmp(self,x,y):  #比较左+右,右+左,判断哪个大,然后返回
        s1=str(x)+str(y)
        s2=str(y)+str(x)
        if s1<=s2:
            return s2
        if s1>s2:
            return s1

    def PrintMinNumber(self,numbers):
        if not numbers:
            return ''
        numbers.sort(reverse=True)  #由大到小排序
        #不断替换index为0,1的值为cmp的返回值,直至最后数组中仅剩一个元素
        while len(numbers)>1:
            numbers[0]=self.cmp(numbers[0],numbers[1])
            numbers.remove(numbers[1])
        return numbers[0]

7、数字在排序数组中出现的次数

问题:统计一个数字在排序数组中出现的次数。

# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        count=0
        if not data or k not in data:
            return 0
        for i in data:
            if i==k:
                count+=1
        return count

8、数组中只出现一次的数字

问题:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

# -*- coding:utf-8 -*-
class Solution:
    # 返回[a,b] 其中ab是出现一次的两个数字
    def FindNumsAppearOnce(self, array):
        # write code here
        number=[]
        for i in array:
            if i in number:
                number.remove(i)
            else:
                number.append(i)
        return number

9、数组中重复的数字

问题:在一个长度为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
        if numbers==None or numbers==[]:
            return False
        data=[]
        for i in numbers:
            if i in data:
                duplication[0]=i
                return True
            else:
                data.append(i)
        return False

10、构建乘积数组

问题:给定一个数组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]。不能使用除法。

思路一:下三角用连乘可以求得,上三角,从下向上也是连乘。先算下三角中的连乘,即先算出B[i]中的一部分,然后倒过来按上三角中的分布规律,把另一部分也乘进去。

# -*- coding:utf-8 -*-
class Solution:
    def multiply(self, A):
        # write code here
        if not A:
            return []
        #计算左三角
        num=len(A)
        B=[None]*num
        B[0]=1
        for i in range(1,num):
            B[i]=B[i-1]*A[i-1]
        #计算右三角,自下而上
        #保留上次的计算结果乘本轮新的数,因为只是后半部分进行累加,所以设置一个temp,能够保留上次的结果
        temp=1
        for i in range(num-2,-1,-1): #从后往前遍历,不算最后一个(num-1),第一个for循环已经计算了
            temp*=A[i+1]
            B[i]*=temp
        return B

思路二:两层for循环,进行连乘,中间判断一下i != j即可。

# -*- coding:utf-8 -*-
class Solution:
    def multiply(self, A):
        # write code here
        n=len(A)
        B=[1]*n
        for i in range(n):
            for j in range(n):
                if i!=j:
                    B[i]*=A[j]
        return B

 

 

 

 

全部评论

相关推荐

评论
点赞
1
分享
牛客网
牛客企业服务