1. 程式人生 > 其它 >劍指offer打卡-2

劍指offer打卡-2

技術標籤:# 劍指offer資料結構演算法pythonleetcode

劍指offer打卡-2

文章目錄

旋轉陣列中的最小數字

  • 問題描述

    問題描述:
    把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個非減排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。
    例如陣列{3,4,5,1,2}{1,2,3,4,5}的一個旋轉,該陣列的最小值為1。 NOTE:給出的所有元素都大於0,若陣列大小為0,請返回0
    
    解決方案:
    1.
    暴力搜尋 2. 分治法 分治法是不斷的縮小範圍,從而找到符合條件的解 二分法的分析我們知道,陣列可以分為前後兩個遞增陣列,下面的分析也都利用遞增的特性 當numbers[mid] > numbers[high],說明最小值在mid的右邊,縮小範圍low = mid + 1 當numbers[mid] == numbers[high],我們不知道最小值的範圍,但是可以肯定的是去除numbers[high]是沒有影響的,縮小範圍high -= 1 當numbers[mid] < numbers[high],我們知道最小值的不是numbers[mid]就是在mid的左邊,縮小範圍high =
    mid
  • 程式碼(解題思路

    class Solution:
    
        def find_min(self, RotateArray):
    
            # 條件1:陣列大小為空,返回0
            if not RotateArray:
                return None
            
            left = 0
            right = len(RotateArray) - 1
            
            while left < right:
                mid = (left + right)//2
                if RotateArray[
    mid] > RotateArray[right]: left = mid + 1 elif RotateArray[mid] == RotateArray[right]: right -= 1 else: right = mid return RotateArray[left]

    測試樣例:

    obj = Solution()
    Rl1 = [2, 3, 4, 5, 1]
    Rl2 = [3, 4, 5, 1, 2]
    Rl3 = [4, 5, 1, 2, 3]
    Rl4 = [5, 1, 2, 3, 4]
    print(obj.find_min(Rl1), end=" ")
    print(obj.find_min(Rl2), end=" ")
    print(obj.find_min(Rl3), end=" ")
    print(obj.find_min(Rl4), end=" ")
    print(obj.find_min([5, 2, 4]), end=" ")
    print(obj.find_min([5, 5]), end=" ")
    print(obj.find_min([5]), end=" ")
    print(obj.find_min([4, 5, 5, 1, 1, 2, 3]), end=" ")
    

    測試結果:

    1 1 1 1 2 1 5 1 
    

    調整順序使得奇數位於前面

  • 問題描述:

    輸入一個整數陣列,實現一個函式來調整該陣列中數字的順序,使得所有的奇數位於陣列的前半部分,
    所有的偶數位於陣列的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。
    
    解決方案:
    1. 暴力遍歷
    2. sorted
    3.氣泡排序分類
    
  • 程式碼

    冒泡法圖示:

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-r0YV7ayt-1611152667739)(./imgs/氣泡排序.gif)]

    class Solution:
    
        def fun1(self, array):
            """奇數在前,偶數在後,相對位置保持不變"""
            new_arry = []
    
            for i in range(len(array)):
                if array[i] & 1 == 1:  # 二進位制與操作,奇數(***1(奇數) & 0001 = 0001)
                    new_arry.append(array[i])
            for j in range(len(array)):
                if array[j] & 1 == 0:
                    new_arry.append(array[j])
    
            return new_arry
    
        def fun2(self, array):
    
            # sorted 預設降序排列
            return sorted(array, key=lambda x:x%2, reverse=True)
    
        def fun3(self, array):
            """氣泡排序"""
            
            for i in range(len(array) - 1):
                flag = False
                for j in range(len(array) - 1 - i):
                    if array[j] % 2 == 0 and array[j+1] % 2 == 1:
                        # change position
                        array[j], array[j+1] = array[j+1], array[j]
                        flag = True
                if flag is False:
                    break
            return array
                        
            return array
    

包含min函式的棧

  • 問題描述

    問題描述:
    定義棧的資料結構,請在該型別中實現一個能夠得到棧中所含最小元素的min函式(時間複雜度應為O(1))
    解決方案:
    1.構建一個和原棧相同的大小的儲存最小值的序列
    2.合理利用儲存
    list : 6 7 5 8 4
    min  : 6   5   4
    
  • 程式碼

    class Stack:
        
        def __init__(self):
            self.stack = []
            self.min_value = []
    
        def push(self, val):
    
            self.stack.append(val)
    
            if self.min_value:
                # 儲存最小值
                if self.min_value[-1] >= val:
                    self.min_value.append(val)
            else:
                # 初始值
                self.min_value.append(val)
    
        def pop(self):
            if not self.stack:
                return None
            else:
                # 保證有效陣列的最小值
                if self.stack[-1] == self.min_value[-1]:
                    self.min_value.pop()
    
                return self.stack.pop()
    
        def top(self):
    
            if not self.stack:
                return None
            else:
                return self.stack[-1]
    
        def min(self):
            """丟擲最小值,棧頂元素永遠儲存最小值"""
    
            if not self.stack:
                return None
            else:
                return self.min_value[-1]
    

判斷一個序列是否為該棧的彈出序列

  • 問題描述

    問題描述:
        輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否可能為該棧的彈出順序。假設壓入棧的所有數字均不相等
    。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的
    彈出序列。(注意:這兩個序列的長度是相等的)
    
    解決方案:
    使用棧來作為臨時的變換
    Eg:
    1 2 3 4 5
    4 5 3 2 1(可行)
    4 5 3 1 2(元素1不可行, 不滿足棧的性質)
    
  • 例項:壓入順序:1, 2, 3, 4, 5 出棧順序:4, 5, 3, 2, 1?

    步驟

    操作

    棧中元素

    彈出數字第一個為4,先找到4

    1

    1入棧

    1

    2

    2入棧

    12

    3

    3入棧

    123

    4

    4入棧

    1234

    此時棧頂元素等於出棧順序的第一個,找到了,下一步就是要出棧該元素

    5

    4出棧

    123

    4出棧順序往後移動,指向5

    6

    5入棧

    1235

    此時棧頂元素等於出棧順序的第一個,找到了,下一步就是要出棧該元素

    7

    5出棧

    123

    45出棧往後移動指向3

    8

    3出棧

    12

    453因為棧頂元素等於出棧元素

    9

    2出棧

    1

    4532因為棧頂元素等於出棧元素

    10

    1出棧

    45321出完瞭如果佔為空且出棧序列中沒有了其他就表示為true

  • 程式碼(解題思路

    class Solution:
    
        def find_seq_exist(self, push_value, pop_values):
            """判斷序列"""
    
            if not push_value or len(pop_values) == len(push_value):
                return None
    
            stack = []
            index = 0
            for item in push_value:
                stack.append(item)
                while stack and stack[-1] == pop_values[index]:
                    stack.pop()
                    index += 1
    
            return True if stack == [] else False
    

從尾到頭列印連結串列

  • 問題描述

    問題描述:
    輸入一個連結串列,按連結串列從尾到頭的順序返回一個ArrayList
    
    解決方案:
    1. 使用列表儲存結點,並翻轉
    2.3. 遞迴
    fun(node.next) + [node.val]
    [] + [8] + [7] + [5]
    [8, 7, 5]
    
  • 程式碼(解題思路

    # 版本一
    class Solution:
    
        @staticmethod
        def PrintListFromTailToHead(listNode):
            if not listNode:
                return []
    
            result = []
            while listNode:
                result.append(listNode.val)
                listNode = listNode.next
    
            result.reverse()
    
            return result
    
    
    # 版本二
    class Solution1:
    
        @staticmethod
        def PrintListFromTailToHead(listNode):
    
            if not listNode:
                return []
    
            stack = []  # 棧
            result = []
    
            while listNode:
                stack.append(listNode.val)
                listNode = listNode.next
            while stack:
                result.append(stack.pop())
    
            return result
    
    
    # 版本三(遞迴:遞迴就是一棧,先進後出)
    class Sulution2:
    
        def PrintListFromTailToHead(self, listNode):
            
            if not listNode:
                return []
    
            return self.PrintListFromTailToHead(listNode.next) + [listNode.val]
    

參考

資料結構與演算法題目

劍指offer(python)

旋轉陣列的通用解決辦法