java判断时间区间 隔天_每日一题 | Day 15: 327. 区间和的个数

如果你爱上了一朵在一颗星星的花,那么你看所有的星星都像开着花一样。那是多么美好啊,天空中盛开着无数朵花,无数朵你所爱的花。

46f8b7eb3fbd1b7345251342eec32547.png

题目描述给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lowerupper
区间和 S(i, j) 表示在 nums 中,位置从 ij 的元素之和,包含 ij (i ≤ j)

说明:
最直观的算法复杂度是 O(n2) ,请在此基础上优化你的算法。

示例:
输入: nums = [-2,5,-1], lower = -2, upper = 2,
输出: 3 
解释: 3个区间分别是: [0,0], [2,2], [0,2],它们表示的和分别为: -2, -1, 2。
题解 官方题解,颇有深度,很难理解,被打击的心塞塞的,小白只能用简单暴力法来躺躺水,能AC也算是leetcode大发善心了?。这道题分享的题解参考价值不太大,旨在个人打卡,不过考点真的值得去回味,前缀和+哈希也是用的多的,很奇特,另外还可以采用归并的思路进行求解。

方法1:暴力法

两次遍历,找出符合条件的所有和。

代码(Java):

 1class Solution {
2    public int countRangeSum(int[] nums, int lower, int upper) {
3        int ans = 0;
4        for (int i = 0; i  5            long sum = 0;
6            for(int j = i; j  7                sum += nums[j];
8                if(sum >= lower && sum <= upper){
9                    ans++;
10                }
11            }
12        }
13        return ans;
14    }
15}
方法2:前缀和+哈希

参考 560. 和为K的子数组,采用前缀和+哈希方法,对范围内的数据进行遍历求解,类似暴力求解,运行时间还没有暴力求解快。

代码(Java):

 1class Solution {
2    public int countRangeSum(int[] nums, int lower, int upper) {
3        int ans = 0; 
4        int n = nums.length;
5        if(n == 0){
6            return ans;
7        }
8        long []preSum = new long[n+1];
9        preSum[0] = 0;
10        for(int i = 1; i 11            preSum[i] = preSum[i-1] + nums[i-1];
12        }
13
14        for(int k = lower; k <= upper; ++k){
15            Map map = new HashMap<>();16            map.put(0l, 1l);17            for(int i = 1; i 18                if(map.containsKey(preSum[i] - k)){19                    ans += map.get(preSum[i] - k);20                }21                map.put(preSum[i], map.getOrDefault(preSum[i], 0l) + 1);22            }23        }24        return ans;25    }26}
方法3、前缀和+归并 1、计算数组的前缀和,只需要前缀和数组中preSum[j] - preSum[i-1]在lower和upper范围内那么数组中的[i,j]的和,就符合条件。 2、采用归并排序的思想,对前缀和进行判断;
 1class Solution {
2    public int countRangeSum(int[] nums, int lower, int upper) {
3        int ans = 0;
4        if(nums.length == 0){
5            return ans;
6        }
7        long []preSum = new long[nums.length + 1]; 
8        preSum[0] = 0;
9        for(int i = 1; i 10            preSum[i] = preSum[i - 1] + nums[i - 1];
11        }
12        return mergeCount(preSum, lower, upper, 0, preSum.length - 1);
13    }
14
15    private int mergeCount(long []sum, int lower, int upper, int left, int right){
16        if(left == right){
17            return 0;
18        } else {
19            int mid = (left + right) >> 1;
20            int a1 = mergeCount(sum, lower, upper, left, mid);
21            int a2 = mergeCount(sum, lower, upper, mid + 1, right);
22            int res = a1 + a2;
23
24            // 计算区间对的个数
25            int i = left;
26            int l = mid + 1;
27            int r = mid + 1;
28            while(i <= mid){
29                while(l <= right && sum[l]- sum[i] 30                    l++;
31                }
32                while(r <= right && sum[r] - sum[i] <= upper){
33                    r++;
34                }
35                res += r - l;
36                i++;
37            }
38
39            // 合并两个排序数组
40            long[] sorted = new long[right - left + 1];
41            int p = left;
42            int q = mid + 1;
43            int pos = 0;
44            while(p <= mid && q <= right){
45                if(sum[p] <= sum[q]){
46                    sorted[pos++] = sum[p++];
47                }else{
48                    sorted[pos++] = sum[q++];
49                }
50            }
51            while(p <= mid){
52                sorted[pos++] = sum[p++];
53            }
54            while(q <= right){
55                sorted[pos++] = sum[q++];
56            }
57
58            for (int j = 0, k = left; j 59                sum[k] = sorted[j];
60            }
61            return res;
62        }
63    }
64}

每一件事情,最难的不是开始,而是坚持!

(LeetCode历史刷题回顾)

5. 最长回文子串

8.字符串转整数

13. 罗马数字转整数
14. 最长公共前缀

33. 搜索旋转排序数组

46. 全排列
57.插入区间
58. 最后一个单词的长度
70.爬楼梯
74. 搜索二维矩阵
92. 反转链表 II
124. 二叉树中的最大路径和

127.单词接龙

160. 相交链表
234. 回文链表
236. 二叉树的最近公共祖先
300. 最长上升子序列
328. 奇偶链表

349.两个数组的交集

415. 字符串相加
876. 链表的中间结点

941. 有效的山脉数组

1356.根据数字二进制下 1 的数目排序

© THE END 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值