劍指offer之Python實現(二)

面試題11:旋轉數字的最小數字

# -*- coding:utf-8 -*-
'''
把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。
輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。
例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。
NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
'''
#折半查找(Binary Search)技術,又稱爲二分查找。前提是順序存儲。時間複雜度爲O(logn),考慮到具有n個節點的完全二叉樹的深度爲logn +1
#在二分查找中,兩個指針分別指向第一個元素和最後一個元素。
#本題的思路就是用二分查找法的思路尋找這個最小的元素。

class Solution:
    def  minNumberInRotateArray(self,rotateArray):
        if len(rotateArray)==0:
            return 0
        low=0
        high=len(rotateArray)-1
        mid=0
        while rotateArray[low]>=rotateArray[high]:#前面的數組大於等於後面的數組
            if high-low==1:
                mid=high
                break
            mid=(low+high)/2
             #考慮到三值相等的情況
            if rotateArray[low] == rotateArray[high] and rotateArray[low] == rotateArray[mid]:
                return self.MinInOrder(rotateArray, low, high)
            if rotateArray[low]<=rotateArray[mid]:
                low=mid
            elif rotateArray[mid]<=rotateArray[high]:
                high=mid

        return rotateArray[mid]


    def MinInOrder(self, array, front, end):
        result = array[0]
        for i in array[front:end+1]:
            if i < result:
                result = i
        return result
s=Solution()
print(s.minNumberInRotateArray([1,1,1,0,1]))

面試題15:二進制中1的個數

# -*- coding:utf-8 -*-
#輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。
#把一個整數減去1,再和原整數做與運算,會把該整數最右邊的1變成0.
class Solution:
    def NumberOf1(self, n):
        # write code here
        count=0
        if n<0:
            n=n& 0xffffffff
        while n:

            n=(n-1)&n
            count += 1
        return count

s=Solution()
print(s.NumberOf1(-2))

2的整數次方

# -*- coding:utf-8 -*-
#輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。
#把一個整數減去1,再和原整數做與運算,會把該整數最右邊的1變成0.
#判斷是不是2的整數次方。若是,只有有一個1,其餘皆爲0.所以只要判斷經過一次減一再與自己的與遠算之後是不是爲0.
class Solution:
    def NumberOf2(self, n):
        # write code here
        count=0
        if n<0:
            return False
        if (n-1)&n==0:
            return True
        else:
            return False

s=Solution()
print(s.NumberOf2(3))

兩數不同的位數

# -*- coding:utf-8 -*-
#輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。
#把一個整數減去1,再和原整數做與運算,會把該整數最右邊的1變成0.
#判斷是不是2的整數次方。若是,只有有一個1,其餘皆爲0.所以只要判斷經過一次減一再與自己的與遠算之後是不是爲0.
#判斷兩數不同的位數,只需要先異或,不同的則爲真“1”,再統計1的個數。
class Solution:
    def NumberOf1(self, n):
        # write code here
        count=0
        if n<0:
            n=n& 0xffffffff
        while n:

            n=(n-1)&n
            count += 1
        return count
    def NumberOf3(self, m,n):
        # write code here
        diff=m^n
        count=0
        while diff:
            count+=1
            diff=(diff-1)&diff
        return count

s=Solution()
print(s.NumberOf3(10,13))

面試題16:數值的整數次方

# -*- coding:utf-8 -*-
#給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。
#注意指數爲負數的情況,底數是零且指數是負數的情況。
# 在判斷底數base是不是等於0的時候,不能直接寫base==0, 因爲計算機內表示小數時有誤差,只能判斷他們的差的絕對值是不是在一個很小的範圍內
#用右移運算代替除以2.用位與&運算代替求餘%判斷一個數是奇數還是偶數。
class Solution:
    def Power(self, base, exponent):
        if exponent == 0:
            return 1
        if exponent == 1:
            return base
        if exponent == -1:
            return 1/base
        if base==0.0 and exponent<0:
            print"Invalid input"


        result = self.Power(base, exponent >> 1)
        result *= result
        if (exponent & 0x1) == 1:
            result *= base
        return result

S = Solution()
print(S.Power(0, -3))

面試題21:調整數組順序使奇數位於偶數前面

# -*- coding:utf-8 -*-
#輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,
# 所有的偶數位於位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。
class Solution:
    def reOrderArray(self, array):#此方法不能保證相對位置不變
        if len(array)==0:
            return
        if len(array)==1:
            return array
        low=0
        high=len(array)-1
        while low < high:
            while low < high and array[low] & 0x01 ==1:#前面的若是奇數,則往後移動指針,注意這邊用while循環,表示如果一直是奇數的話,那就一直往後移,直到不是奇數,而不是用if判斷。
                low+=1
            while low < high and array[high] & 0x01==0:#後面的若是偶數,則往前移動指針
                high-=1
            if low<high:
                array[low],array[high]=array[high],array[low]

        return array

    def reOrderArray2(self,array):#列表解析,是奇數的就放在left裏,是偶數就放在right裏。
        left=[x for x in array if x &0x1==1]
        right=[x for x in array if not x&0x1==1]
        return left+right

    def reOrderArray3(self,array):
        if len(array)==0:
            return []
        if len(array)==1:
            return array
        OddList=[]
        EvenList=[]
        for item in array:
            if item & 0x01==1:
                OddList.append(item)
            if item & 0x01==0:
                EvenList.append(item)
        return OddList+EvenList


# 可擴展性的解法
    # 注意在一個函數的輸入中, 輸入另一個函數的寫法func = self.fucName, funcName不需要加括號
    def Reorder(self, pData, length, func):
        if length == 0:
            return

        pBegin = 0
        pEnd = length - 1

        while pBegin < pEnd:
            while pBegin < pEnd and not func(pData[pBegin]):
                pBegin += 1
            while pBegin < pEnd and func(pData[pEnd]):
                pEnd -= 1

            if pBegin < pEnd:
                pData[pBegin], pData[pEnd] = pData[pEnd], pData[pBegin]
        return pData

    def isEven(self, n):
        return not n & 0x1

    def isNegtive(self, n):
        return n >= 0

    def ReorderOddEven(self, pData):
        length = len(pData)
        return self.Reorder(pData, length, func=self.isNegtive)

s=Solution()
print(s.reOrderArray([1,2,3,4,5,7,8]))
print(s.reOrderArray2([1,2,3,4,5,7,8]))
print(s.reOrderArray3([1,2,3,4,5,7,8]))

擴展解法

# -*- coding:utf-8 -*-
#把數組中的數按照大小分爲兩部分,所有負數都在非負數的前面
#能被三整除的數都在不能被3整除的數的前面
class Solution:
    def ReOrder(self,pData,length,func):
        if length==0:
            return

        pBegin=0
        pEnd=length-1

        while pBegin<pEnd:
            while pBegin<pEnd and  func(pData[pBegin]):
                pBegin+=1
            while pBegin<pEnd and not func(pData[pEnd]):
                pEnd-=1
            if pBegin<pEnd:
                pData[pBegin],pData[pEnd]=pData[pEnd],pData[pBegin]
        return pData

    def isOdd(self,n):#判斷是不是奇數
        return  n &0x01

    def isNegative(self,n):
        return n>=0

    def OddEven(self,pData):
        length=len(pData)
        return self.ReOrder(pData,length,func=self.isOdd)
s=Solution()
print s.OddEven([1,2,3,4,5,6])

面試題22:鏈表中倒數第k個節點

# -*- coding:utf-8 -*-
#輸入一個鏈表,輸出該鏈表中倒數第k個結點。
#從1開始計數,則尾節點就是倒數第一個節點
#魯棒性:輸入的頭節點的指針爲空指針。以head爲頭結點的鏈表的節點總數少於k。輸入參數k爲0.
class ListNode:
    def __init__(self, x):
       self.val = x
       self.next = None

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        if head==None:
            return
        if k<=0:
            return

        pAhead=head
        pBehind=None
        for i in range(1,k):
            if pAhead.next !=None:
               pAhead=pAhead.next
            else:
                return

        pBehind=head

        while pAhead.next !=None:
            pAhead=pAhead.next
            pBehind=pBehind.next
        return pBehind

node1=ListNode(10)
node2=ListNode(18)
node3=ListNode(2)
node1.next=node2
node2.next=node3
s=Solution()
print s.FindKthToTail(node1,2).val

面試題24:翻轉鏈表

# -*- coding:utf-8 -*-
#輸入一個鏈表,反轉鏈表後,輸出鏈表的所有元素。
#關鍵是要定義三個指針,當前的節點,它的前一個節點,後一個節點。
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        pReversedHead=None
        cur=pHead
        pre=None
        while cur !=None:
            if cur.next==None:
                pReversedHead=cur
            tmp=cur.next
            cur.next=pre
            pre=cur
            cur=tmp
        return pReversedHead

    def ReverseList2(self,pHead):
        # if pHead==None:
        #     return None
        # if pHead.next==None:
        #     return pHead
        if not pHead or not pHead.next:
            return pHead
        else:
            pReversedHead=self.ReverseList2(pHead.next)
            pHead.next.next=pHead
            pHead.next=None#去掉往後的指針
        return pReversedHead


node1=ListNode(10)
node2=ListNode(11)
node3=ListNode(8)
node1.next=node2
node2.next=node3
s=Solution()
print(s.ReverseList2(node1).val)

面試題25:合併兩個排序的鏈表

# -*- coding:utf-8 -*-
#輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。
#注意魯棒性。第一個鏈表爲空,返回第二個鏈表;第二個鏈表爲空,返回第一個鏈表;兩個都是空。得到空鏈表。
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
class Solution:
    # 返回合併後列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if pHead1==None:
            return pHead2
        elif pHead2==None:
            return pHead1
        pMergeHead=None
        if pHead1.val < pHead2.val:
            pMergeHead=pHead1
            pMergeHead.next=self.Merge(pHead1.next,pHead2)
        else:
            pMergeHead=pHead2
            pMergeHead.next=self.Merge(pHead1,pHead2.next)
        return pMergeHead

node1 = ListNode(1)
node2 = ListNode(3)
node3 = ListNode(5)
node1.next = node2
node2.next = node3

node4 = ListNode(2)
node5 = ListNode(4)
node6 = ListNode(6)
node4.next = node5
node5.next = node6

S = Solution()
head=S.Merge(node1, node4)
print(head.val)

未完待續。。。

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