剑指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)

未完待续。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值