《劍指offer》第10-20題:矩形覆蓋到包含min函數的棧

10 矩形覆蓋

  我們可以用21的小矩形橫着或者豎着去覆蓋更大的矩形。請問用n個21的小矩形無重疊地覆蓋一個2n的大矩形,總共有多少種方法?比如n=3時,23的矩形塊有3種覆蓋方法:
在這裏插入圖片描述

'''
第一塊有兩種方式:橫着放和豎着放
橫着放對應爲方法爲f(n-2);
豎着放下一步的放方法爲f(n-1);
所以總的放的方法爲f(n)=f(n-1)+f(n-2);
和第7題一樣,方法不外乎循環和遞歸兩種
這裏只寫循環迭代法。其他方法查看第7題
'''

class Solution:
    def rectCover(self, number):
        # write code here
        if number == 0:
            return 0
        pre,cur = 0,1
        index = 0
        while index < number:
            pre,cur = cur,pre+cur
            index += 1
        return cur

11 二進制中1的個數

  輸入一個整數,輸出該數32位二進制表示中1的個數。其中負數用補碼錶示

'''
python中 使用模將負數轉化:n = n & 0xffffffff,然後再進行減1做與運算


先了解下計算機中原碼反碼補碼
        eg:十進制 3 轉換爲二進制: 00000011
原碼:
    是一種計算機中對數字的二進制定點表示方法。原碼錶示法在數值前面增加了一位符號位(即最高位爲符號位):
    正數該位爲0,負數該位爲1(0有兩種表示:+0和-0),其餘位表示數值的大小。
    eg:十進制 3 轉換爲二進制的原碼: 00000011,
             -3的話:10000011
             1的話: 00000001
             -1的話:10000001
反碼:
    正數的反碼是其本身
    負數的反碼是在其原碼的基礎上, 符號位不變,其餘各個位取反.
        eg: 十進制1:原碼:00000001 反碼:00000001
                -1:原碼:10000001 反碼:11111110
補碼:
    正數的補碼就是其本身
    負數的補碼是在其原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1. (即在反碼的基礎上+1)
        eg: 十進制1:原碼:00000001 反碼:00000001 補碼:00000001
                -1:原碼:10000001 反碼:11111110 補碼:11111111
'''
'''
方法一:內置函數
'''
class Solution1:
    def NumberOf1(self, n):
        # write code here
        #整數轉二進制
        return str(bin(n)).count("1") if n >= 0 else str(bin(n & 0xffffffff)).count("1")
'''
方法二:位運算
負數的右移運算會在高位進行補1,如果沒考慮這一點,可能導致程序陷入死循環
可以使用與運算實現1的個數統計
'''
class Solution3:
    def NumberOf1(self, n):
        maxNum = (1 << (32 - 1))
        flag = 1
        count = 0
        while flag <= maxNum:
            print(maxNum,flag,count,n & flag)
            if n & flag:
                count += 1
            flag = flag << 1
        return count

12 數值的整數次方

  給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。
保證base和exponent不同時爲0

'''
方法一:公式法 & 內置函數 
'''
class Solution1:
    def Power(self, base, exponent):
        return pow(base,exponent)
        # or
        # return base ** exponent

'''
方法二:暴力法:次方累乘
'''
class Solution2:
    def Power(self, base, exponent):
        result = 1
        for i in range(abs(exponent)):#次方的最初表達式
            result *= base
        return result if exponent >= 0 else 1/result #根據正負返回不同的值

'''
方法三:遞歸法
想了老半天沒理清楚遞歸法,先略過...
'''
class Solution3:
    def Power(self, base, exponent):
        pass

13 調整數組順序使奇數位於偶數前面.

  輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,所有的偶數位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。

'''
排序,奇奇 偶偶相對位置不變
'''
'''
方法一:暴力法
將奇數和偶數分別存放到新數組中,拼接
O(n)
'''
class Solution1:
    def reOrderArray(self, array):
        # write code here
        odd,even = [],[]
        for i in array:
            even.append(i) if i%2 ==0 else odd.append(i)
        return odd+even

14 鏈表中倒數第K個節點

  輸入一個鏈表,輸出該鏈表中倒數第k個結點。

'''
方法一:暴力法:將所有元素存到列表中
'''
class Solution1:
    def FindKthToTail(self, head:ListNode, k):
        nodeList = []
        while head != None:
            nodeList.append(head)
            head = head.next
        if k > len(nodeList) or k < 1:
            return None
        return nodeList[-k]

'''
方法二:先統計,再查詢
'''
class Solution2:
    def FindKthToTail(self, head, k):
        if not head:
            return None
        nodeList = head
        count = 0
        while nodeList:
            nodeList = nodeList.next
            count += 1
        if k > count:
            return None
        while count - k:
            head = head.next
            k += 1
        return head

15 反轉鏈表

   輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。

'''
方法一:
'''
class Solution1:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        if not pHead:#空
            return pHead
        pre = pHead
        cur = pHead.next
        if cur is None:#一個節點
            return pHead
        next_p = cur.next
        if next_p is None:#兩個節點
            pre.next = None
            cur.next = pre
            return cur
        pre.next = None#節點數>=3
        while next_p != None:
            cur.next = pre
            pre = cur#指針移動
            cur = next_p
            next_p = next_p.next
        cur.next = pre
        return cur

'''
方法二:
參考鏈接:https://www.nowcoder.com/questionTerminal/75e878df47f24fdc9dc3e400ec6058ca?f=discussion
pHead始終指向要反轉的結點
cur 指向反轉後的首結點
每反轉一個結點,把pHead結點的下一個結點指向cur, cur指向pHead成爲反轉後首結點, 再把pHead向前移動一個結點直至None結束
'''
class Solution2:
    # 返回ListNode
    def ReverseList(self, pHead):
        cur = None
        while pHead:
            tmp = pHead.next
            pHead.next = cur
            cur = pHead
            pHead = tmp
        return cur

16 合併兩個排序的鏈表

  輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
''''
方法一:遞歸
'''
class Solution:
    # 返回合併後列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if not pHead1:#判空
            return pHead2
        if not pHead2:
            return pHead1

        if pHead1.val < pHead2.val:
            pHead1.next = self.Merge(pHead1.next, pHead2)
            return pHead1
        else:
            pHead2.next = self.Merge(pHead1, pHead2.next)
            return pHead2

'''
方法二:暴力法
'''
class Solution2:
    # 返回合併後列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if not pHead1:
            return pHead2
        if not pHead2:
            return pHead1

        pNode1 = pHead1
        pNode2 = pHead2
        if pNode1.val <= pNode2.val:
            pNode = pNode1
            pNode1 = pNode1.next
        else:
            pNode = pNode2
            pNode2 = pNode2.next
        pHead = pNode

        while pNode1 or pNode2:
            if not pNode1:
                pNode.next = pNode2
                pNode2 = pNode2.next
            elif not pNode2:
                pNode.next = pNode1
                pNode1 = pNode1.next
            else:
                if pNode1.val <= pNode2.val:
                    pNode.next = pNode1
                    pNode1 = pNode1.next
                else:
                    pNode.next = pNode2
                    pNode2 = pNode2.next
            pNode = pNode.next
        return pHead

17樹的子結構

  輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
'''
方法一:遞歸遍歷
'''
class Solution:
    def HasSubtree(self, pRoot1, pRoot2):
        # write code here
        if not pRoot1 or not pRoot2:
            return False

        result = False
        if pRoot1.val == pRoot2.val:
            result = self.Tree1ContainTree2(pRoot1,pRoot2)

        if not result:
            if pRoot1.left:
                result = self.HasSubtree(pRoot1.left,pRoot2)
            if not result and pRoot1.right:
                result = self.HasSubtree(pRoot1.right,pRoot2)
        return result

    def Tree1ContainTree2(self,pRoot1,pRoot2):
        if not pRoot2:#遍歷完,說明是A的子樹,返回True
            return True
        if not pRoot1:
            return False

        if pRoot1.val != pRoot2.val:
            return False

        return self.Tree1ContainTree2(pRoot1.left, pRoot2.left) and self.Tree1ContainTree2(pRoot1.right,pRoot2.right)

18 二叉樹的鏡像

  操作給定的二叉樹,將其變換爲源二叉樹的鏡像。

在這裏插入圖片描述

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
'''
方法一:遞歸
'''
class Solution1:
    # 返回鏡像樹的根節點
    def Mirror(self, root):
        # write code here
        if not root:
            return root
        #終止條件
        if not root.left and not root.right:
            return
        if root.left and root.right:
            root.left, root.right = root.right, root.left
            self.Mirror(root.left)
            self.Mirror(root.right)
        elif root.left  and not root.right:
            root.left, root.right = None, root.left
            self.Mirror(root.right)
        elif not root.left and root.right:
            root.left, root.right = root.right, None
            self.Mirror(root.left)
        return root
'''
方法二:遞歸簡化
'''
class Solution2:
    # 返回鏡像樹的根節點
    def Mirror(self, root):
        # write code here
        if root:
            root.left, root.right = root.right, root.left
            self.Mirror(root.left)
            self.Mirror(root.right)
        return root

19 順時針打印矩陣

  輸入一個矩陣,按照從外向裏以順時針的順序依次打印出每一個數字,例如,如果輸入如下4 X 4矩陣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
則依次打印出數字
1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

'''
方法一:
根據打印規則,第一次打印第一行,接着打印最後一列(除去第一個元素,後面類似),打印最後一行,打印第一列
第二圈第一行,依次打印,
'''
import numpy as np
class Solution1:
    # matrix類型爲二維列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        rowsTotal = len(matrix)
        colsTotal = len(matrix[0])
        if not rowsTotal and not colsTotal:
            return None

        left, right, top, bottom = 0, colsTotal - 1, 0, rowsTotal - 1#上下左右四個邊界代表的行列值
        result = []
        while left <= right and top <= bottom:
            #從左到右一行
            for i in range(left,right+1):
                result.append(matrix[top][i])
            #從上到下一列
            for j in range(top+1,bottom+1):
                result.append(matrix[j][right])
            #從右到左一行
            if top != bottom:
                for m in  range(right-1,left-1,-1):
                    result.append(matrix[bottom][m])
            #從下到上一列
            if left != right:
                for n in range(bottom-1,top,-1):
                    result.append(matrix[n][left])
            left += 1
            right -= 1
            top += 1
            bottom -= 1
        return result

20 包含min函數的棧

  定義棧的數據結構,請在該類型中實現一個能夠得到棧中所含最小元素的min函數(時間複雜度應爲O(1))。
注意:保證測試中不會當棧爲空的時候,對棧調用pop()或者min()或者top()方法。

'''
方法一:內置函數min()
...忽略題目O(1)的要求
'''
class Solution1:
    def __init__(self):
        self.stack = []

    def push(self, node):
        # write code here
        self.stack.append(node)

    def pop(self):
        # write code here
        return self.stack.pop()

    def top(self):
        # write code here
        return self.stack[-1]

    def min(self):
        # write code here
        return min(self.stack)


'''
方法二:藉助一個輔助棧,輔助棧最後一個元素存放的一定是最小的元素
'''
class Solution2:
    def __init__(self):
        self.stack = []
        self.minEleStack = []

    def push(self, node):
        # write code here
        self.stack.append(node)
        if not self.minEleStack:
            self.minEleStack.append(node)
        elif node < self.minEleStack[-1]:
            self.minEleStack.append(node)
        else:
            self.minEleStack.append(self.minEleStack[-1])

    def pop(self):
        # write code here
        if not self.stack:
            return None
        self.minEleStack.pop()
        return self.stack.pop()

    def top(self):
        # write code here
        if not self.stack:
            return None
        return self.stack[-1]
    def min(self):
        # write code here
        return self.minEleStack[-1]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章