1. 程式人生 > >python資料結構之貪心演算法

python資料結構之貪心演算法

目錄

  1. 貪心演算法的基礎知識
  2. 分糖果 (LeetCode 455)
  3. 搖擺序列(LeetCode 376)
  4. 移除K個數字(LeetCode 402)
  5. 跳躍遊戲1 (LeetCode 55)
  6. 跳躍遊戲2 (LeetCode 45)
  7. 射擊氣球(LeetCode 452)

1. 貪心演算法的基礎知識

貪心演算法就是每次都貪心地選擇當前最好的那個(區域性最優解),不去考慮以後的情況,而且選擇了就不能夠“反悔”了,如果原問題滿足貪心選擇性質和最優子結構,那麼最後得到的解就是最優解。

貪心演算法和其他的演算法比較有明顯的區別,動態規劃每次都是綜合所有子問題的解得到當前的最優解(全域性最優解),而不是貪心地選擇;回溯法是嘗試選擇一條路,如果選擇錯了的話可以“反悔”,也就是回過頭來重新選擇其他的試試。

2. 分糖果 (LeetCode 455)

2.1題目

Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie. Each child i has a greed factor gi, which is the minimum size of a cookie that the child will be content with; and each cookie j has a size sj. If sj >= gi, we can assign the cookie j to the child i, and the child i will be content. Your goal is to maximize the number of your content children and output the maximum number.
Note:
You may assume the greed factor is always positive.
You cannot assign more than one cookie to one child.
Example 1:
Input: [1,2,3], [1,1]
Output: 1
Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3.
And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content.
You need to output 1.

2.2思路

對貪婪係數和餅乾大小都按從小到大的順序排序,當滿足餅乾大小大於等於貪婪係數時,計數加1,直到貪婪係數或餅乾大小遍歷結束。

2.3程式碼

class Solution(object):
    def findContentChildren(self, g, s):
        """
        :type g: List[int]
        :type s: List[int]
        :rtype: int
        """
        i = len(g) - 1
        j = len(s) - 1
        cnt = 0
g = sorted(g) s = sorted(s) while min(i,j) >= 0: if s[j] >= g[i]: cnt += 1 j -= 1 i -= 1 return cnt

3. 搖擺序列(LeetCode 376 Wiggle Subsequence)

3.1題目

A sequence of numbers is called a wiggle sequence if the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with fewer than two elements is trivially a wiggle sequence.

For example, [1,7,4,9,2,5] is a wiggle sequence because the differences (6,-3,5,-7,3) are alternately positive and negative. In contrast, [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the first because its first two differences are positive and the second because its last difference is zero.

Given a sequence of integers, return the length of the longest subsequence that is a wiggle sequence. A subsequence is obtained by deleting some number of elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order.

Examples:
Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.

Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].

Input: [1,2,3,4,5,6,7,8,9]
Output: 2

3.2思路

一次遍歷,nums[i] - nums[i-1] != 0且與上一個差異號時,則滿足條件,結果+1,也就是說在遍歷過程中將連續遞增的部分和連續遞減的部分分別進行合併,實現o(n)時間複雜度。

3.3程式碼

class Solution(object):
    def wiggleMaxLength(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        size = len(nums)
        if size < 2:
            return size
        delta = nums[1] - nums[0]
        ans = 1 + (delta != 0)
        for i in range(2, size):
            newdelta = nums[i] - nums[i-1]
            if newdelta != 0 and newdelta * delta <= 0:
                ans += 1
                delta = newdelta
        return ans

4. 移除K個數字(LeetCode 402 Remove K Digits)

4.1題目

Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.

Note:
The length of num is less than 10002 and will be ≥ k.
The given num does not contain any leading zero.

Example 1:
Input: num = “1432219”, k = 3
Output: “1219”
Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.
Example 2:
Input: num = “10200”, k = 1
Output: “200”
Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.
Example 3:
Input: num = “10”, k = 2
Output: “0”
Explanation: Remove all the digits from the number and it is left with nothing which is 0.

4.2思路

逐次刪除,尋找數字中第一次出現nums[i]>nums[i+1]的位置,刪除nums[i],則nums[i]=nums[:i]+nums[i+1:]。如此迴圈k次結束。

4.3程式碼

class Solution(object):
    def removeKdigits(self, num, k):
        """
        :type num: str
        :type k: int
        :rtype: str
        """
        while k > 0:
            k -= 1
            i = 0
            while i < len(num) - 1:
                if num[i] > num[i+1]:
                    break
                i += 1
            num = num[:i] + num[i+1:]
        if len(num) == 0:
            return '0'
        else:
            return str(int(num))

5. 跳躍遊戲1 (LeetCode 55 Jump Game)

5.1題目

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

For example:
A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

5.2思路

從起始位置開始判斷,不斷擴充套件可以的到達的位置,最後判斷可以到達的位置是否超過最後的位置,如果大於等於,則可以到達,否則,不可以。

5.3程式碼

class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        size = len(nums)
        if size <= 1:
            return True
        reach = 1
        i = 0
        while i < reach and reach < size:
            reach = max(reach, i + 1 + nums[i])
            i += 1
        return reach >= size

6. 跳躍遊戲2 (LeetCode 45 Jump Game II)

6.1題目

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

For example:
Given array A = [2,3,1,1,4]

The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)

6.2思路

該題與上一題的區別在於求解到達最後所使用的最小步數。思路是不斷擴充套件可以調到的區域,在這個區域內把下一個可達的區域算出來,直到結束。

6.3程式碼

class Solution(object):
    def jump(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        size = len(nums)
        if size <= 1:
            return 0
        left = 0
        right = 0
        ans = 0
        while True:
            old_right = right
            ans += 1
            while left <= old_right:
                new_right = left + nums[left]
                if new_right >= size - 1:
                    return ans
                right = max(right, new_right)
                left += 1

7. 射擊氣球(LeetCode 452 Minimum Number of Arrows to Burst Balloons)

7.1題目

There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it’s horizontal, y-coordinates don’t matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons.

An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.

Example:

Input:
[[10,16], [2,8], [1,6], [7,12]]

Output:
2

Explanation:
One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).

7.2思路

求擊爆所有氣球所需要的最少箭數,將所有氣球的座標按照左座標從小到大進行排序,求包含公共部分線段的個數。

7.3程式碼

class Solution(object):
    def findMinArrowShots(self, points):
        """
        :type points: List[List[int]]
        :rtype: int
        """
        size = len(points)
        if size <= 1:
            return size
        points = sorted(points, key = lambda x: x[0])
        left = points[0][0]
        right = points[0][1]
        count = 1
        for i in range(1, size):
            if points[i][0] >= left and points[i][0] <= right:
                left = points[i][0]
                if points[i][1] < right:
                    right = points[i][1]
            else:
                count += 1
                left = points[i][0]
                right = points[i][1]
        return count

相關推薦

python資料結構貪心演算法

目錄 貪心演算法的基礎知識 分糖果 (LeetCode 455) 搖擺序列(LeetCode 376) 移除K個數字(LeetCode 402) 跳躍遊戲1 (LeetCode 55) 跳躍遊戲2 (LeetCode 45) 射擊氣球(LeetCode 45

python資料結構KMP演算法的實現

我相信網上已經有很多關於KMP演算法的講解,大致都是關於部分匹配表的實現思路和作用,還有就是目標串的下標不變,僅改變模式串的下標來進行匹配,確實用KMP演算法,當目標串很大模式串很小時,其效率很高的,但都是相對而言。至於對於部分匹配表的作用以及實現思路,建議看一下這篇文章寫的是比較易懂的

python資料結構串——概述和基本演算法

概述: 字串(string)簡稱串,也是一種線性結構。在python中和array差不多,因為py的陣列也可以包括各種字元(在C/Java一類的語法中,陣列必須是同一種資料型別的元素)。線性結構,有限序列,是主要特點。串其中可以包含各種元素,也是計算機主要處理的一類物件。因

資料結構排序演算法(五)

// 索引堆 function swap(arr, x, y) {             var temp = arr[x];         

Python資料結構: 棧與佇列

棧(stacks) 是一種只能通過訪問其一端來實現資料儲存與檢索的線性資料結構,具有後進先出(last in first out,LIFO)的特徵 stack = [] stack.append("A") #A入棧 stack.append("B") #B入棧 st

python資料結構二叉樹

這裡用python 實現了二叉樹 # Definition for a binary tree node. class TreeNode: def __init__(self, x): self.val = x self.left =

資料結構排序演算法

JavaScript實現排序演算法 程式碼實現 const ArrayList = function() { let array = [], length = 0; this.insert = function(item) {

Cris 複習Python日記(四):Python 資料結構序列和列表

1. 簡單認識序列和列表 # 序列 # 序列是Python 中最基本的資料結構,用於儲存一組有序的資料,所有資料都在序列中擁有一個唯一索引,並且按照元素新增的順序來指定序列 # 序列的分類 # 1.

python資料結構棧和佇列

1.功能實現 之前文章有,可以點開看看 棧 佇列 2.應用(1)括號匹配及字尾表示式 class Solution(object): def isValid(self, s): """ :type s: str :rtype

python資料結構連結串列

1.功能實現 連結串列(Linked list)是一種常見的基礎資料結構,是一種線性表,但是並不會按線性的順序儲存資料,而是在每一個節點裡存到下一個節點的指標(Pointer)。由於不必須按順序儲存,連結串列在插入的時候可以達到O(1)的複雜度,比另一種線性表順序錶快得多,但是查詢一個節點或者訪

python 資料結構列表操作

lt = [1, 2, 3, 4, 5] #列表取值與切片 #切片規則與字串相同 print(lt[0])#1 print(lt[-1])#5 print(lt[1:3])#[2, 3] print(len(lt))#列表長度5 # 修改元素 lt[0] = 100 print(lt)#[100,

資料結構演算法(快慢指標原理)

如何找到未知長度單鏈表的中間節點? 思路1:   遍歷單鏈表獲取長度n,n/2再遍歷得到中間節點,時間複雜度為O(n+n/2)=O(3/2n) 思路2:利用快慢指標原理,設定兩個指標*search,*mid,都指向單鏈表第一個元素,假設單鏈表有頭結點,則為  search

python資料結構字典方法

字典是一種通過名字或者關鍵字引用的得資料結構,其鍵可以是數字、字串、元組,這種結構型別也稱之為對映。字典型別是Python中唯一內建的對映型別,基本的操作包括如下:  (1)len():返回字典中鍵—值對的數量;  (2)d[k]:返回關鍵字對於的值;  (3)d[k]

python資料結構字串方法

1.capitalize():將字串中首字母轉換成大寫,其餘字元轉換成小寫 Str="this is string example from runoob ...wow!!!" print("Str.capitalize():",Str.capitalize())#該方法返回一個首字母大寫的字串

python資料結構字串格式化

字串格式化: 1.簡單運用 字串型別格式化採用format()方法,基本使用格式是:      <模板字串>.format(<逗號分隔的引數>) 呼叫format()方法後會返回一個新的字串,引數從0 開始編號

python資料結構列表、元組

(與字串和元組的區別)列表是可變的----------可以改變列表的內容,並且列表中含有很多有用的專門的方法。 list函式: 可以將字串建立成列表 程式碼: a=list('Hello') print(a) 輸出: ['H', 'e', 'l', 'l', 'o'] 基本的

python資料結構序列及其操作

序列       在Python中最基本的資料結構是序列(sequence)。序列中的每個元素被分配一個序號----即元素的位置,也稱索引。索引從0開始,0,1,2,3,...。也可以從最後一個數開始,標記為-1,依次為-1,-2,-3.... 列表與元組的區別

python資料結構深淺拷貝

Python中深淺拷貝詳解 變數-引用-物件(可變物件,不可變物件)-切片-拷貝(淺拷貝,深拷貝) 變數:在Python中一切都是物件,比如:3,3.14,“Hello world”,【1,2,3,4】,{‘a’:1}…. 輸出: 甚至連Type其本身也是物件,type物

python 資料結構佇列和棧

# 棧是一種特殊的線性表,僅能線上性表的一端操作,棧頂允許操作,棧底不允許操作。 # 棧的特性:後進先出 class Stack(object): """棧""" def __init__(self): self.items=[] def is_empty(s

python 資料結構連結串列

單向連結串列也叫單鏈表,是連結串列中最簡單的一種形式,它的每個節點包含兩個域,一個資訊域(元素域)和一個連結域。這個連結指向連結串列中的下一個節點,而最後一個節點的連結域則指向一個空值。 class Node(object):     """節點類""" &nbs