《劍指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

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章