2021.8.28 每日一题
给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i]) 。
请返回 nums 的动态和。
示例 1:
输入:nums = [1,2,3,4]
输出:[1,3,6,10]
解释:动态和计算过程为 [1, 1+2, 1+2+3, 1+2+3+4] 。
示例 2:
输入:nums = [1,1,1,1,1]
输出:[1,2,3,4,5]
解释:动态和计算过程为 [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1] 。
示例 3:
输入:nums = [3,1,2,10,1]
输出:[3,4,6,16,17]
提示:
1 <= nums.length <= 1000
-10^6 <= nums[i] <= 10^6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/running-sum-of-1d-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
秒了
class Solution {
public int[] runningSum(int[] nums) {
for(int i = 1; i < nums.length; i++){
nums[i] = nums[i] + nums[i - 1];
}
return nums;
}
}
2021.8.29 每日一题
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和 。
示例 1:
输入:arr = [1,4,2,5,3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1,4,2] = 7
[4,2,5] = 11
[2,5,3] = 10
[1,4,2,5,3] = 15
我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58
示例 2:
输入:arr = [1,2]
输出:3
解释:总共只有 2 个长度为奇数的子数组,[1] 和 [2]。它们的和为 3 。
示例 3:
输入:arr = [10,11,12]
输出:66
提示:
1 <= arr.length <= 100
1 <= arr[i] <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-all-odd-length-subarrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
刚开始就想用数学规律来做的,结果想了半天没想出来
前缀和吧,然后遍历每个长度和开始位置
class Solution {
public int sumOddLengthSubarrays(int[] arr) {
int l = arr.length;
int[] pre = new int[l + 1];
for(int i = 1; i <= l; i++){
pre[i] = pre[i - 1] + arr[i - 1];
}
int res = 0;
for(int i = 1; i <= l; i += 2){
for(int j = 0; j <= l - i; j++){
res += pre[j + i] - pre[j];
}
}
return res;
}
}
数学解法,思路就是统计每个数在奇数长度子数组中出现的次数
怎么统计呢,这个比较不好想
就是统计左右两边的个数,加上自身要成为一个奇数长度子数组,所以左右两边个只能同为奇数或者同为偶数
遍历一遍,把所有数出现的次数乘以当前值加起来就行了
这种思想,包括怎么在一个长度的数组中求奇偶数的个数,也可以巩固一下
class Solution {
public int sumOddLengthSubarrays(int[] arr) {
//前缀和过后,写一下On的数学解法
//主要就是统计每个位置的数出现过多少次
//考虑每个位置左右两边数的奇偶性,只有左右两边都是奇数个或者偶数个,才可以
//但是这个怎么写呢
int l = arr.length;
int res = 0;
for(int i = 0; i < l; i++){
int left = i - 0; //左边的个数
int right = l - i - 1; //右边的个数
//左边奇数有多少个,left / 2 + right % 2,右边也是right / 2 + right & 2
//偶数,左边有left / 2 + 1, 右边right / 2 + 1,加1是因为有0
res += ((left + 1) / 2) * ((right + 1) / 2) * arr[i];
res += (left / 2 + 1) * (right / 2 + 1) * arr[i];
}
return res;
}
}
2021.8.30 每日一题
给定一个正整数数组 w ,其中 w[i] 代表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex ,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。
例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。
也就是说,选取下标 i 的概率为 w[i] / sum(w) 。
示例 1:
输入:
[“Solution”,“pickIndex”]
[[[1]],[]]
输出:
[null,0]
解释:
Solution solution = new Solution([1]);
solution.pickIndex(); // 返回 0,因为数组中只有一个元素,所以唯一的选择是返回下标 0。
示例 2:
输入:
[“Solution”,“pickIndex”,“pickIndex”,“pickIndex”,“pickIndex”,“pickIndex”]
[[[1,3]],[],[],[],[],[]]
输出:
[null,1,1,1,1,0]
解释:
Solution solution = new Solution([1, 3]);
solution.pickIndex(); // 返回 1,返回下标 1,返回该下标概率为 3/4 。
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 0,返回下标 0,返回该下标概率为 1/4 。
由于这是一个随机问题,允许多个答案,因此下列输出都可以被认为是正确的:
[null,1,1,1,1,0]
[null,1,1,1,1,1]
[null,1,1,1,0,0]
[null,1,1,1,0,1]
[null,1,0,1,0,0]
…
诸若此类。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/random-pick-with-weight
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一次做这种产生随机数的题,首先明确如何产生随机数才能使取得下标的概率满足要求
就是按照所给的公式,先计算sum(w),然后计算前缀和,每个下标对应的前缀和就是这个下标的取值范围
当取到一个随机数后,用二分查找,找到对应的下标,返回就行了
class Solution {
//随机化,怎么设计呢,相当于一个下标对应一个数据的区间,怎么写呢
//先计算sum(w),就是整个数据产生的范围,最大10的9次,然后在这个范围内生成一个随机数,
//查看这个随机数在哪个下标对应的范围内
int sum = 0;
Random rd = new Random();
int[] pre;
int n;
public Solution(int[] w) {
n = w.length;
pre = new int[n + 1];
for(int i = 1; i <= n; i++){
pre[i] = pre[i - 1] + w[i - 1];
sum += w[i - 1];
}
}
public int pickIndex() {
int idx = rd.nextInt(sum);
//找idx所在的区间下标
int left = 0;
int right = n;
while(left < right){
int mid = (right - left + 1) / 2 + left;
if(pre[mid] <= idx){
left = mid;
}else{
right = mid - 1;
}
}
return left;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(w);
* int param_1 = obj.pickIndex();
*/