1502. 判断能否形成等差数列
1502. 判断能否形成等差数列
题目
A sequence of numbers is called an arithmetic progression if the difference between any two consecutive elements is the same.
Given an array of numbers arr, return true if the array can be rearranged to form anarithmetic progression. Otherwise, return false.
Example 1:
Input: arr = [3,5,1]
Output: true
Explanation: We can reorder the elements as [1,3,5] or [5,3,1] with differences 2 and -2 respectively, between each consecutive elements.
Example 2:
Input: arr = [1,2,4]
Output: false
Explanation: There is no way to reorder the elements to obtain an arithmetic progression.
Constraints:
2 <= arr.length <= 1000-10^6 <= arr[i] <= 10^6
题目大意
给你一个数字数组 arr 。
如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。
如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。
示例 1:
输入: arr = [3,5,1]
输出: true
解释: 对数组重新排序得到 [1,3,5] 或者 [5,3,1] ,任意相邻两项的差分别为 2 或 -2 ,可以形成等差数列。
示例 2:
输入: arr = [1,2,4]
输出: false
解释: 无法通过重新排序得到等差数列。
提示:
2 <= arr.length <= 1000-10^6 <= arr[i] <= 10^6
解题思路
等差数列的特性:
- 对于一个等差数列,最大值和最小值确定后,每两个相邻数之间的差是固定的 (
gap)。 - 给定最小值
min和间隔gap,等差数列中每个数字arr[i]都应该满足:arr[i] = min + i * gap - 如果某个数不在其目标位置(即
arr[i] ≠ min + i * gap),可以将其与目标位置上的数交换,直到所有数都在目标位置。
- 对于一个等差数列,最大值和最小值确定后,每两个相邻数之间的差是固定的 (
检查位置是否正确:
- 如果当前数字已经在正确位置(即
arr[i] === min + i * gap),则继续处理下一个数字。 - 如果当前数字不在正确位置:
- 通过目标位置公式计算正确位置
pos = (arr[i] - min) / gap。 - 检查
pos是否有效(范围在[0, n-1]之间的整数),并确保目标位置的数字与当前数字不同,避免重复。
- 通过目标位置公式计算正确位置
- 如果当前数字已经在正确位置(即
交换数字:
- 如果发现数字不在目标位置,交换
arr[i]和arr[pos]。 - 重复检查新的
arr[i],直到该位置数字满足等差数列的条件。
- 如果发现数字不在目标位置,交换
继续遍历:
- 处理下一个数字,直到所有数字都在正确位置。
复杂度分析
- 时间复杂度:
O(n),遍历数组两次:一次找最大值和最小值,一次调整元素位置。 - 空间复杂度:
O(1),原地修改数组,无额外空间。
代码
/**
* @param {number[]} arr
* @return {boolean}
*/
var canMakeArithmeticProgression = function (arr) {
let min = Infinity,
max = -Infinity;
// 找到数组的最小值和最大值
for (let num of arr) {
if (num > max) max = num;
if (num < min) min = num;
}
const n = arr.length;
const gap = (max - min) / (n - 1);
// 特殊情况,数组中的数全部相同时,也是等差数列,返回 true
if (gap === 0) return true;
let i = 0;
while (i < n) {
// 检查当前元素是否在正确位置
if (arr[i] === min + i * gap) {
i++;
} else {
const diff = arr[i] - min;
// 检查当前元素是否满足等差公式
if (diff % gap !== 0) return false;
const pos = diff / gap;
// 检查是否出现重复
if (arr[pos] === arr[i]) return false;
// 交换到正确位置
let temp = arr[pos];
arr[pos] = arr[i];
arr[i] = temp;
}
}
return true;
};
相关题目
| 题号 | 标题 | 题解 | 标签 | 难度 | 力扣 |
|---|---|---|---|---|---|
| 1630 | 等差子数组 | 数组 哈希表 排序 | 🟠 | 🀄️ 🔗 |
