[LeetCode] 560. 和爲K的子數組(和值數組,哈希)

560. 和爲K的子數組

給定一個整數數組和一個整數 k,你需要找到該數組中和爲 k 的連續的子數組的個數。
在這裏插入圖片描述
解題思路: 本題一開始以爲是用滑動窗口解題,但是在寫代碼的時候發現,整數數組的值有正有負,和值也不是單調的,因此窗口的收縮方向不好判斷,於是換了種思路。此題的背景是求和,而且是求序列的連續子集和,那麼爲了降低時間複雜度,往往我們會將0到當前索引位置的和值求出來放在一個和值數組中,然後求某段子數組的和值,比如[i,j],只需計算SUM[i,j]=sum[j]-sum[i]+num[i],但是算法的時間複雜度爲O(N2)O(N^2),好像至此,OJ也能通過這個解法。然後看了grandyang的解法,再結合本題給出的標籤,哈希,題目認爲的最優解法是哈希解法。

哈希解題思路:我們可以分析下面這個圖,這段序列取自給定數組nums,左邊界是nums的左邊界,右邊界是nums中間某個點,我們分析這個當前狀態,我們的和值k是有中間某段連續序列組成,因此我們依然在遍歷的過程中將當前位置到0-index點的和值求出來,但是我們不用保存在一個數組,僅僅維護一個到當前位置的和值sum即可,在遍歷的過程中,我們將這個和值與它出現的個數用哈希映射起來,那麼當我們遍歷到圖中這個狀態時,我們要判斷和值k是否存在,只需判斷和值sum-k是否存在,順着這個思路,此題可解。

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int res = 0, sum = 0, n = nums.size();
        unordered_map<int, int> m{{0,1}};
        for (int i = 0; i < n; ++i) {
            sum += nums[i];
            res += m[sum - k];
            ++m[sum];
        }
        return res;
    }
};

總結

對連續求和值的題做一個簡單的總結和回顧。連續和值的解法一般用和值數組即可降低一個維度的時間複雜度,這是通常解法,若涉及到判斷和值個數的問題,比如這題,那麼需要想到用哈希來記錄值和個數的映射,這個直接想比較難想到,但是另一個想法我們是很常見的,即,當我們需要判斷或者找尋的和值爲k時,若已知我們當前位置到某個位置(常規是起點0-index)的和值,那我們只需要判斷或者找尋從起點位置到某個位置的和值爲sum-k的序列,就可以解決和值爲k的問題了。

參考資料

https://www.cnblogs.com/grandyang/p/6810361.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章