1588. 所有奇数长度子数组的和
题目描述
给你一个正整数数组 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
提示:
1 <= arr.length <= 1001 <= arr[i] <= 1000
题解
枚举
class Solution {
public:
int sumOddLengthSubarrays(vector<int>& arr) {
int ret = 0, n = arr.size();
int i, j;
for (i = 0; i < n; ++i) {
int sum = 0;
for(j = i; j < n; ++j) {
sum += arr[j];
if ( (j - i + 1) & 1 ) {
ret += sum;
}
}
}
return ret;
}
};
首先枚举起点下标i,然后枚举终点下标j,枚举过程中不断进行累加,当j - i + 1是奇数时代表数组长度为奇数,将累加的和加到结果中即可
1
1 4 2
1 4 2 5 3
4
4 2 5
2
2 5 3
5
3
1848. 到目标元素的最小距离
题目描述
给你一个整数数组 nums (下标 从 0 开始 计数)以及两个整数 target 和 start ,请你找出一个下标 i ,满足 nums[i] == target 且 abs(i - start) 最小化 。注意:abs(x) 表示 x 的绝对值。
返回 abs(i - start) 。
题目数据保证 target 存在于 nums 中。
示例 1:
输入: nums = [1,2,3,4,5], target = 5, start = 3
输出: 1
解释: nums[4] = 5 是唯一一个等于 target 的值,所以答案是 abs(4 - 3) = 1 。
提示:
1 <= nums.length <= 10001 <= nums[i] <= 10^40 <= start < nums.lengthtarget存在于nums中
题解
枚举
class Solution {
public:
int getMinDistance(vector<int>& nums, int target, int start) {
int ret = 10000;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] == target && abs(i - start) < ret) { // 1
ret = abs(i - start);
}
}
return ret;
}
};
- 可以把
父if语句里的子if语句,利用&&写在父if语句中,运行速度好像也快了
1652. 拆炸弹
题目描述
你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。
为了获得正确的密码,你需要替换掉每一个数字。所有数字会 同时 被替换。
- 如果
k > 0,将第i个数字用 接下来k个数字之和替换。 - 如果
k < 0,将第i个数字用 之前k个数字之和替换。 - 如果
k == 0,将第i个数字用0替换。
由于 code 是循环的, code[n-1] 下一个元素是 code[0] ,且 code[0] 前一个元素是 code[n-1] 。
给你 循环 数组 code 和整数密钥 k ,请你返回解密后的结果来拆除炸弹!
示例 1:
输入: code = [5,7,1,4], k = 3
输出: [12,10,16,13]
解释: 每个数字都被接下来 3 个数字之和替换。解密后的密码为 [7+1+4, 1+4+5, 4+5+7, 5+7+1]。注意到数组是循环连接的。
示例 2:
输入: code = [1,2,3,4], k = 0
输出: [0,0,0,0]
解释: 当 k 为 0 时,所有数字都被 0 替换。
示例 3:
输入: code = [2,4,9,3], k = -2
输出: [12,5,6,13]
解释: 解密后的密码为 [3+9, 2+3, 4+2, 9+4] 。注意到数组是循环连接的。如果 k 是负数,那么和为 之前 的数字。
提示:
n == code.length1 <= n <= 1001 <= code[i] <= 100-(n - 1) <= k <= n - 1
题解
class Solution {
public:
vector<int> decrypt(vector<int>& code, int k) {
vector <int> ret; // 因为后面会用到code数组替换前的元素
int n = code.size();
int i, j, val;
for (i = 0; i < n; ++i) {
val = 0;
if (k > 0) {
for(j = i + 1; j <= i + k; ++j) {
val += code[j % n];
}
} else if (k < 0) {
for(j = i - 1; j >= i + k; --j) {
val += code[ (j % n + n) % n];
}
}
ret.push_back(val);
}
return ret;
}
};
对于每个 code[i],如果 k > 0,则从 i+1 到 i+k 去找元素进行累加,下标索引的时候,为了下标不会越界,需要对 n 进行取模;对于每个 code[i],如果 k < 0,则从 i-1 到 i+k 去找元素进行累加,下标有可能变成负数,所以需要对 n 取模以后,再加上 n,再进行取模。原理可以参见《夜深人静写算法(三)初等数论》
- 这题需要注意的是
数组下标越界问题,如何使下标形成循环,利用%
1640. 能否连接形成数组
题目描述
给你一个整数数组 arr ,数组中的每个整数 互不相同 。另有一个由整数数组构成的数组 pieces,其中的整数也 互不相同 。请你以 任意顺序 连接 pieces 中的数组以形成 arr 。但是,不允许 对每个数组 pieces[i] 中的整数重新排序。
如果可以连接 **pieces 中的数组形成 arr ,返回 true ;否则,返回 false 。
示例 1:
输入: arr = [15,88], pieces = [[88],[15]]
输出: true
解释: 依次连接 [15] 和 [88]
示例 2:
输入: arr = [49,18,16], pieces = [[16,18,49]]
输出: false
解释: 即便数字相符,也不能重新排列 pieces[0]
示例 3:
输入: arr = [91,4,64,78], pieces = [[78],[4,64],[91]]
输出: true
解释: 依次连接 [91]、[4,64] 和 [78]
提示:
1 <= pieces.length <= arr.length <= 100sum(pieces[i].length) == arr.length1 <= pieces[i].length <= arr.length1 <= arr[i], pieces[i][j] <= 100arr中的整数 互不相同pieces中的整数 互不相同(也就是说,如果将pieces扁平化成一维数组,数组中的所有整数互不相同)
题解
class Solution {
public:
bool canFormArray(vector<int>& arr, vector<vector<int>>& pieces) {
int i = 0, j, k;
bool flag = false;
while(i < arr.size()) {
flag = false;
for (j = 0; j < pieces.size(); ++j) {
if(pieces[j][0] != arr[i]) {
continue;
}
for (k = 0; k < pieces[j].size(); ++k) {
if (pieces[j][k] == arr[i]) {
++i;
flag = true;
} else {
return true;
}
}
if (i == arr.size()) {
return true;
}
}
if (!flag) {
return false;
}
}
return true;
}
};
首先定义两个指针,一个指针指向原数组,另一个指针用于遍历 pieces 数组; 如果某一次遍历不能找到一块匹配的块,则返回 false;如果完整匹配,则原数组指针自增,当原数组指针等于数组长度时返回 true。