《算法设计与分析》第十一周作业

《算法设计与分析》第十一周作业

标签(空格分隔): 课堂作业

姓名:李**
学号: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;
    }
};

猜你喜欢

转载自blog.csdn.net/Ray0758/article/details/84197043