第一题
题目
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和
思路- 没想出来,所以解题都是看的题解,之后复习时候补充
1、暴力破解,不过这个暴力破解主要需要思考的就是从哪循环,循环到哪,哪里结束
补充:
- 三层循环,第一次层循环表示,从哪个元素开始遍历(start表示)
- 第二层循环,表示start开始的奇数长度的数组
- 已经在第二层循环到技奇数长度的数组了,第三层循环,获取每个数组的元素进行加和
2、使用前缀和-因为会有很多重复的数组计算,比如,子数组长度为3时,一定会用到子数组长度为1时计算的值,子数组长度为5时,一定会用到子数组长度为3时的计算的值...
补充:
- 创建一个新数组,这个数组的每一个元素表示,输入数组的前i项和
- 两层循环-第一次层循环表示,从哪个元素开始遍历(start表示)
- 第二层循环,表示start开始的奇数长度的数组
- 在第二层循环里就可以直接用上第一步的新数组
代码
1、暴力破解
public int sumOddLengthSubarrays(int[] arr) {
int sum = 0;
int n = arr.length;
for (int start = 0; start < n; start++) {
for (int length = 1; start + length <= n; length += 2) {
int end = start + length - 1;
for (int i = start; i <= end; i++) {
sum += arr[i];
}
}
}
return sum;
}
2、前缀和
class Solution {
public int sumOddLengthSubarrays(int[] arr) {
int n = arr.length;
int[] prefixSums = new int[n + 1];
for (int i = 0; i < n; i++) {
prefixSums[i + 1] = prefixSums[i] + arr[i];
}
int sum = 0;
for (int start = 0; start < n; start++) {
for (int length = 1; start + length <= n; length += 2) {
int end = start + length - 1;
// 为什么减呢,因为你从start开始的,得减下去start之前的数组元素和
sum += prefixSums[end + 1] - prefixSums[start];
}
}
return sum;
}
第二题
题目
给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i 位客户在第 j 家银行托管的资产数量。返回最富有客户所拥有的 资产总量 。
客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户
思路
遍历啊,我也只能想到遍历,这,应该没有别的方法吧
代码
public int maximumWealth(int[][] accounts) {
int max = 0;
for(int i = 0; i < accounts.length; i++) {
int sum = 0;
for(int j = 0; j < accounts[0].length; j++) {
sum+= accounts[i][j];
};
if(sum > max) {
max = sum;
};
};
return max;
}
第三题
题目
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作
思路
哇哦,就是说刷题啥用吧,这不就来了,第二道双指针类型题,详见day01第一题
代码
public void moveZeroes(int[] nums) {
if(nums.length == 1) {
return ;
}
int i = 0;
int j = 1;
while(i < nums.length -1 && j < nums.length) {
if(nums[i] == 0) {
if(nums[j] == 0) {
j++;
}else {
nums[i] = nums[j];
nums[j] =0;
i++;
j=i+1;
}
}else {
i++;
j=i+1;
}
}
}