前缀和 差分数组编程题集合

命运对每个人都是一样的,不一样的是各自的努力和付出不同,付出的越多,努力的越多,得到的回报也越多,在你累的时候请看一下身边比你成功却还比你更努力的人,这样,你就会更有动力。

导读:本篇文章讲解 前缀和 差分数组编程题集合,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2
示例 2:

输入:nums = [1,2,3], k = 3
输出:2

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subarray-sum-equals-k

前缀和加哈希表优化,单纯的使用前缀和本题会超过时间限制,所以在前缀和的基础上加上哈希表进行优化。

 public int subarraySum(int[] nums, int k) {
        int pre=0;
        int result=0;
        Map<Integer,Integer> map=new HashMap<>();
        map.put(0,1);
       for(int i=0;i<nums.length;i++){
          pre+=nums[i];
          if(map.containsKey(pre-k))
              result+=map.get(pre-k);
          map.put(pre,map.getOrDefault(pre,0)+1);

       }
       return result;
    }

滑动窗口,本题我也考虑过使用滑动窗口,但是提交的时候发现很多的问题,对于类似的题数组的值必须是全是正数或负数的可以使用滑动窗口,既有正数也有负数的此类题目并不适用滑动窗口。

下面是动态规划解法,但是数据量很大的时候就会时间超时。代码如下

//dp[i][j]表示数组中i索引到j的元素的和
    public int subarraySum(int[] nums, int k) {
        int dp[][]=new int[nums.length][nums.length];
        int result=0;
        for(int i=0;i<nums.length;i++){
            for(int j=i;j<nums.length;j++){
                if(i==j)
                dp[i][i]=nums[i];
                else
                dp[i][j]=dp[i][j-1]+nums[j];
                if(dp[i][j]==k)
                    result++;
            }
        }
        return result;


    }

给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:

子数组大小 至少为 2 ,且
子数组元素总和为 k 的倍数。
如果存在,返回 true ;否则,返回 false 。

如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。0 始终视为 k 的一个倍数。

示例 1:

输入:nums = [23,2,4,6,7], k = 6
输出:true
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6 。
示例 2:

输入:nums = [23,2,6,4,7], k = 6
输出:true
解释:[23, 2, 6, 4, 7] 是大小为 5 的子数组,并且和为 42 。 
42 是 6 的倍数,因为 42 = 7 * 6 且 7 是一个整数。
示例 3:

输入:nums = [23,2,6,4,7], k = 13
输出:false

 public static boolean checkSubarraySum(int[] nums, int k) {
        int pre=0;
        if(nums.length<2)
            return false;
        Map<Integer,Integer> map=new HashMap<>();
        map.put(0,-1);
        for(int i=0;i<nums.length;i++){
            pre+=nums[i];
            if(map.containsKey(pre%k)){
              if(i-map.get(pre%k)>=2){
                  return true;
              }
            }
            else
            map.put(pre%k,i);
        }
        return false;
    }

 

给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。

示例 1:

输入: nums = [0,1]
输出: 2
说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
示例 2:

输入: nums = [0,1,0]
输出: 2
说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。

public static int findMaxLength(int[] nums) {
		 	if(nums.length<2)
		 		return 0;
		 int pre=0;
		 int max=0;
		 Map<Integer, Integer> map=new HashMap<>();
		 map.put(0, -1);
		 for(int i=0;i<nums.length;i++) {
			 if(nums[i]==0)
				 pre=pre-1;
			 else
			     pre=pre+nums[i];
			 if(map.containsKey(pre)) {
				 max=Math.max(max, i-map.get(pre));
			 }
			 else {
				 map.put(pre, i);
			 }
		 }
		 return max;
		 	
	    }

 

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。

子数组 是数组的 连续 部分。

示例 1:

输入:nums = [4,5,0,-2,-3,1], k = 5
输出:7
解释:
有 7 个子数组满足其元素之和可被 k = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
示例 2:

输入: nums = [5], k = 9
输出: 0

 public int subarraysDivByK(int[] nums, int k) {
          int pre=0;   
        Map<Integer,Integer> map=new HashMap<>();
        map.put(0,1);
        int result=0;
        for(int i=0;i<nums.length;i++){
            pre+=nums[i];
            int key=(pre%k+k)%k;
            if(map.containsKey(key)){
              result+=map.get(key);
            }
            map.put(key,map.getOrDefault(key, 0)+1);
        }
        return result;
    }

 

 

差分数组:

对于数组a[i],我们令d[i]=a[i]-a[i-1]  (特殊的,第一个为d[1]=a[1]),则d[i]为一个差分数组。

我们发现统计d数组的前缀和sum数组,有

sum[i]=d[1]+d[2]+d[3]+…+d[i]=a[1]+a[2]-a[1]+a[3]-a[2]+…+a[i]-a[i-1]=a[i],即前缀和sum[i]=a[i];

因此每次在区间[l,r]增减x只需要令d[l]+x,d[r+1]-x,就可以保证[l,r]增加了x,而对[1,l-1]和[r+1,n]无影响。 复杂度则是O(n)的

1109. 航班预订统计

难度中等453收藏分享切换为英文接收动态反馈

这里有 n 个航班,它们分别从 1 到 n 进行编号。

有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。

请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。

示例 1:

输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]
解释:
航班编号        1   2   3   4   5
预订记录 1 :   10  10
预订记录 2 :       20  20
预订记录 3 :       25  25  25  25
总座位数:      10  55  45  25  25
因此,answer = [10,55,45,25,25]
 public  int[] corpFlightBookings(int[][] bookings, int n) {
		 
		 int arr[]=new int[n+2];
		 for(int i=0;i<bookings.length;i++) {
			 int m=bookings[i][0];
			 int nn=bookings[i][1];
			 int x=bookings[i][2];
			 arr[m]+=x;
			 arr[nn+1]-=x;
		 }
    
		 int sum[]=new int[n];
		 sum[0]=arr[1];
		 for(int i=1;i<n;i++)
			 sum[i]=sum[i-1]+arr[i+1];
		 return sum;
	 }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/143044.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!