簡體   English   中英

回溯解決方案的大 O 計算范圍內的排列

[英]Big O of backtracking solution counts permutations with range

我有一個問題,我一直在努力解決我的解決方案時間和空間復雜性:

給定一個整數數組(可能重復) Aminlowhigh是整數。 A中項目的總組合數:

  • low <= A[i] <= high
  • 每個組合至少有min數字。
  • 一個組合中的數字可以重復,因為它們在 A 中被認為是唯一的,但組合不能重復。 例如: [1,1,2] -> 組合: [1,1],[1,2],[1,1,2]可以,但[1,1],[1,1], [1,2], [2,1] ...不是。

示例: A=[4, 6, 3, 13, 5, 10], min = 2, low = 3, high = 5

A中有4種組合有效整數的方法: [4,3],[4,5],[4,3,5],[3,5]

這是我的解決方案,它有效:

class Solution:
    def __init__(self):
        pass
    def get_result(self, arr, min_size, low, high):
        return self._count_ways(arr, min_size, low, high, 0, 0)
    def _count_ways(self, arr, min_size, low, high, idx, comb_size):
        if idx == len(arr):
            return 0
        count = 0
        for i in range(idx, len(arr)):
            if arr[i] >= low and arr[i] <= high:
                comb_size += 1
                if comb_size >= min_size:
                    count += 1
                count += self._count_ways(arr, min_size, low, high, i + 1, comb_size)
                comb_size -= 1
        return count

我使用回溯所以:

時間: O(n!)因為對於每個整數,我都會在最壞的情況下檢查每個剩余的整數 - 當所有整數都可以形成組合時。

空間: O(n)因為我最多需要在調用堆棧上調用 n 次,並且我只使用 2 個變量來跟蹤我的組合。

我的分析正確嗎?

另外,有點超出范圍但是:我應該做某種記憶來改進它嗎?

如果我正確理解您的要求,那么您的算法太復雜了。 你可以這樣做:

  1. 計算數組B包含A lowhigh之間的所有元素。
  2. 返回sum of Choose(B.length, k) for k = min .. B.length ,其中Choose(n,k)n(n-1)..(n-k+1)/k! .

如果您使用記憶化來計算Choose函數的分子/分母,則時間和空間復雜度為O(n) (例如,如果您已經計算了5*4*3 ,則只需要一次乘法即可計算5*4*3*2等等。)。

在你的例子中,你會得到B = [4, 3, 5] ,所以B.length = 3 ,結果是

  Choose(3, 2) + Choose(3, 3) 
= (3 * 2)/(2 * 1) + (3 * 2 * 1)/(3 * 2 * 1) 
= 3 + 1
= 4

您對時間復雜度的分析不太正確。

我明白你在哪里得到O(n!)for i in range(idx, len(arr)):每次遞歸調用循環長度都會減少,所以看起來你在做n*(n-1)*(n-2)*... .

但是,來自長度為m的循環的遞歸調用並不總是包含大小為m-1的循環。 假設您最外層的調用有 3 個元素。 循環遍歷 3 個可能的值,每個值都會產生一個新的調用。 第一個這樣的調用將有一個循環遍歷 2 個值,但下一個調用只遍歷 1 個值,最后一個調用立即命中您的基本情況並停止。 因此,您得到的不是3*2*1=((1+1)+(1+1)+(1+1)) ,而是((1+0)+1+0)

使用大小為n的數組調用_count_ways所需的時間是調用大小為n-1兩倍。 要看到這一點,請考慮大小為n的調用中的第一個分支,即是否選擇第一個元素。 首先我們選擇第一個元素,這會導致大小為n-1的遞歸調用。 其次,我們不選擇第一個元素,這讓我們剩下n-1元素可以迭代,所以就好像我們有一個大小為n-1遞歸調用。

n 的每次增加都會使時間復雜度增加 2 倍,因此您的解決方案的時間復雜度為O(2^n) 這是有道理的:您正在檢查每個組合,並且在一組大小為n的集合中有2^n組合。

但是,由於您只是嘗試計算組合而不是對它們進行處理,因此效率非常低。 請參閱@Mo B. 的答案以獲得更好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM