美团内推 类似题目

来源:互联网 发布:seo搜索引擎是什么 编辑:程序博客网 时间:2024/06/05 17:40

1 leetcode 560  Subarray Sum Equals K  这里不是K的倍数而是K

数组中有0的情况

Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.

Example 1:

Input:nums = [1,1,1], k = 2Output: 2

Note:

  1. The length of the array is in range [1, 20,000].
  2. The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].
(1)暴力解法
把所有可能的子数组都列举出来,依次判断加和是否是K。 O(n^3)O(n3). Considering every possible subarray takes O(n^2)O(n2) time. For each of the subarray we calculate the sum taking O(n)O(n) time in the worst case, taking a total of O(n^3)O(n3) time.
public class Solution {    public int subarraySum(int[] nums, int k) {        int count = 0;        for (int start = 0; start < nums.length; start++) {            for (int end = start + 1; end <= nums.length; end++) {                int sum = 0;                for (int i = start; i < end; i++)                    sum += nums[i];                if (sum == k)                    count++;            }        }        return count;    }}

(2)使用累计和方法 O(n2   O(n)O(n)
构建一个数组,数组sum[i]代表前(i-1)项和,对于子数列
nums[i:j]
nums[i:j], sum[j+1] - sum[i]sum[j+1]sum[i]代表其累加和,设置二维循环判断每一个和。
要注意的是下标的对应
public class Solution {    public int subarraySum(int[] nums, int k) {        int count = 0;        int[] sum = new int[nums.length + 1];        sum[0] = 0;        for (int i = 1; i <= nums.length; i++)            sum[i] = sum[i - 1] + nums[i - 1];        for (int start = 0; start < nums.length; start++) {            for (int end = start + 1; end <= nums.length; end++) {                if (sum[end] - sum[start] == k)                    count++;            }        }        return count;    }}

(3)按行依次累加判断,是(2)的改进,可以通过动态规划思想获得,通过压缩空间,
可以只剩下一个值。O(n2O(1)
public class Solution {    public int subarraySum(int[] nums, int k) {        int count = 0;        for (int start = 0; start < nums.length; start++) {            int sum=0;            for (int end = start; end < nums.length; end++) {                sum+=nums[end];                if (sum == k)                    count++;            }        }        return count;    }}

(4)使用哈希map O(nO(n)
记录(当前累加和,当前累加和出现的次数),遍历一遍数组,同时构建哈希表,每次在哈希表中查找是否存在当前累加和sum-K的数,存在就将他的值加上
class Solution {public:    int subarraySum(vector<int>& nums, int k) {        int sum=0;        map<int,int> p;        int count=0;        p[0]=1;//不可缺少这一项        for(int i=0;i<nums.size();i++)        {            sum+=nums[i];            count+=p[sum-k];            p[sum]++;        }        return count;        }};

leetcode 523. Continuous Subarray Sum 是否存在连续子序列加和是某数的倍数

题意:如果连续子串的加和是给定值的倍数是存在的,就返回true。

思路1:动态规划  O(n^2)
需要把所有可能的情况都判断,直到出现是的情况
难点、易错点:
考虑0的情况。k可能是0。这个也是美团题不能全部通过的一个原因。
要求子数列至少是两个。

class Solution {public:    bool checkSubarraySum(vector<int>& nums, int k) {        int n=nums.size();        if(n<=1) return false;//要求子数列至少是两个        int pre;        int cur;        for(int i=n-1;i>=0;i--)            for(int j=i;j<n;j++)            {                if(i==j)                 {                    cur=nums[j];                }                else                    cur=pre+nums[j];                if(j>i)//子数列至少是两个的时候才有资格判断                {                 if(k!=0&&cur%k==0) return true;                if(k==0&&cur==0) return true;                }                                pre=cur;            }        return false;    }};
思路2:
下面这种方法用了些技巧,那就是,若数字a和b分别除以数字c,若得到的余数相同,那么(a-b)必定能够整除c。这里就不证明了,博主也不会证明。明白了这条定理,那么我们用一个集合set来保存所有出现过的余数,如果当前的累加和除以k得到的余数在set中已经存在了,那么说明之前必定有一段子数组和可以整除k。需要注意的是k为0的情况,由于无法取余,我们就把当前累加和放入set中。还有就是题目要求子数组至少需要两个数字,那么我们需要一个变量pre来记录之前的和,我们每次存入set中的是pre,而不是当前的累积和
class Solution {public:    bool checkSubarraySum(vector<int>& nums, int k) {        int n = nums.size(), sum = 0, pre = 0;        unordered_set<int> modk;        for (int i = 0; i < n; ++i) {            sum += nums[i];            int mod = k == 0 ? sum : sum % k;            if (modk.count(mod)) return true;            modk.insert(pre);            pre = mod;        }        return false;    }};

既然set可以做,一般来说用哈希表也可以做,这里我们建立余数和当前位置之间的映射,由于有了位置信息,我们就不需要pre变量了,之前用保存的坐标和当前位置i比较判断就可以了
public boolean checkSubarraySum(int[] nums, int k) {    Map<Integer, Integer> map = new HashMap<Integer, Integer>(){{put(0,-1);}};;    int runningSum = 0;    for (int i=0;i<nums.length;i++) {        runningSum += nums[i];        if (k != 0) runningSum %= k;         Integer prev = map.get(runningSum);        if (prev != null) {            if (i - prev > 1) return true;        }        else map.put(runningSum, i);    }    return false;}




阅读全文
1 0
原创粉丝点击