英雄联盟六月集训第一日数组

129 阅读2分钟

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 <= 100
  • 1 <= 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 <= 1000
  • 1 <= nums[i] <= 10^4
  • 0 <= start < nums.length
  • target 存在于 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;
    }
};
  1. 可以把 父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.length
  • 1 <= n <= 100
  • 1 <= 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,再进行取模。原理可以参见《夜深人静写算法(三)初等数论》

  1. 这题需要注意的是 数组下标越界问题,如何使下标形成循环,利用 %

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 <= 100
  • sum(pieces[i].length) == arr.length
  • 1 <= pieces[i].length <= arr.length
  • 1 <= arr[i], pieces[i][j] <= 100
  • arr 中的整数 互不相同
  • 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。