1. 程式人生 > >《演算法設計與分析》第十一週作業

《演算法設計與分析》第十一週作業

《演算法設計與分析》第十一週作業

標籤(空格分隔): 課堂作業

文章目錄

姓名:李**
學號:16340114
題目:Continuous Subarray Sum(https://leetcode.com/problems/continuous-subarray-sum/)


題目概要

給定一串數字nums和一個指定的數字k,尋找nums中有無子串的和是k的整數倍數,即
   k

s u m s , k ! = 0  
o r   s u m s = 0 , k
= 0 k|sums,k!=0 or sums=0,k=0

思路

mod[i][j]表示nums[i…j]的和對k求餘之後的餘數。
  mod[i][j]的計算公式如下:
   m o d [ i ] [ j ]   =   1 ,   w h e n   j < i mod[i][j] = -1, when j<i
   m o d [ i ] [ j ]   =   n u m s [ i ] ,   w h e n   j = i mod[i][j] = nums[i], when j=i
   m o d [ i ] [ j ]   =   ( m o d [ i ] [ j ]   +   n u m s [ i ] )   %   k ,   w h e n   j > i mod[i][j] = (mod[i][j] + nums[i]) \% k, when j>i
  特別地,當k為零的時候,去掉取模操作。一段數字求和取模為0,說明這段數能被k整除。而當k為零時,只需找出和為零的一段數即可。
  最後判斷是否存在 m o d [ x ] [ y ] , ( x ! = y ) mod[x][y],(x!=y)為 零即可。

具體實現

根據計算公式算即可,每一步都取模是為了防止上溢。交上去發現記憶體溢位了。。。
  一番思考後發覺這個題目只是找存在而已,不用把所有結果都保留,並且計算mod[i][j]的時候只依賴於mod[i]這一行,所以計算的時候不需要申請一個矩陣,只需要一個能存下一行的一維陣列即可。算完一行之後這個陣列就可以不用保留,留給下一行迴圈利用了。(具體看程式碼)

心得

這周習題課上完之後,總算是學會了用二維陣列去表示問題裡的狀態了,但是我現在做的這題只擊敗了1%的選手,說明這題還是有別的更好的演算法,但這個通用演算法總算是學到了。感覺動態規劃還有很多千奇百怪的變形,學習之路道阻且長呀。

原始碼:

class Solution 
{
public:
    bool checkSubarraySum(vector<int>& nums, int k) 
    {
        int length = nums.size();
        auto mod = vector<int>(length);


        for (int i = 0; i < length; ++i)
        {
            mod[i] = k==0 ? nums[i] : nums[i] % k;

            for (int j = i+1; j < length; ++j)
            {
                mod[j] = mod[j-1] + nums[j];
                mod[j] = k==0 ? mod[j] : mod[j] % k;
                if (mod[j] == 0)
                    return true;
            }
        }

        return false;
    }
};