2757. 生成循环数组的值 🔒
2757. 生成循环数组的值 🔒
题目
Given a circular array arr and an integer startIndex, return a generator object gen that yields values from arr.
The first time gen.next() is called on the generator, it should should yield arr[startIndex].
Each subsequent time gen.next() is called, an integer jump will be passed into the function (Ex: gen.next(-3)).
- If
jumpis positive, the index should increase by that value, however if the current index is the last index, it should instead jump to the first index. - If
jumpis negative, the index should decrease by the magnitude of that value, however if the current index is the first index, it should instead jump to the last index.
Example 1:
Input: arr = [1,2,3,4,5], steps = [1,2,6], startIndex = 0
Output: [1,2,4,5]
Explanation:
const gen = cycleGenerator(arr, startIndex); gen.next().value; // 1, index = startIndex = 0 gen.next(1).value; // 2, index = 1, 0 -> 1 gen.next(2).value; // 4, index = 3, 1 -> 2 -> 3 gen.next(6).value; // 5, index = 4, 3 -> 4 -> 0 -> 1 -> 2 -> 3 -> 4
Example 2:
Input: arr = [10,11,12,13,14,15], steps = [1,4,0,-1,-3], startIndex = 1
Output: [11,12,10,10,15,12]
Explanation:
const gen = cycleGenerator(arr, startIndex); gen.next().value; // 11, index = 1 gen.next(1).value; // 12, index = 2 gen.next(4).value; // 10, index = 0 gen.next(0).value; // 10, index = 0 gen.next(-1).value; // 15, index = 5 gen.next(-3).value; // 12, index = 2
Example 3:
Input: arr = [2,4,6,7,8,10], steps = [-4,5,-3,10], startIndex = 3
Output: [7,10,8,4,10]
Explanation:
const gen = cycleGenerator(arr, startIndex); gen.next().value; // 7, index = 3 gen.next(-4).value; // 10, index = 5 gen.next(5).value; // 8, index = 4 gen.next(-3).value; // 4, index = 1 gen.next(10).value; // 10, index = 5
Constraints:
1 <= arr.length <= 10^41 <= steps.length <= 100-10^4 <= steps[i], arr[i] <= 10^40 <= startIndex < arr.length
题目大意
给定你一个 循环 数组 arr 和一个整数 startIndex ,返回一个生成器对象 gen ,它从 arr 中生成值。第一次调用 gen.next() 时,它应该生成 arr[startIndex] 。每次调用 gen.next() 时,都会传入一个整数参数 jump(例如:gen.next(-3) )。
- 如果
jump是正数,则索引应该增加该值,但如果当前索引是最后一个索引,则应跳转到第一个索引。 - 如果
jump是负数,则索引应减去该值的绝对值,但如果当前索引是第一个索引,则应跳转到最后一个索引。
提示:
1 <= arr.length <= 10^41 <= steps.length <= 100-10^4 <= steps[i], arr[i] <= 10^40 <= startIndex < arr.length
解题思路
需要编写一个生成器函数 cycleGenerator,它接收一个数组 arr 和一个初始索引 startIndex,并返回一个生成器,这个生成器会根据传入的 jump 参数(每次通过 next(jump) 调用)来返回新的数组值。
- 通过
while (true)使得生成器无限循环,因为数组是循环的,且没有明确的终止条件。 - 生成器通过
yield来返回当前索引的元素arr[startIndex]。 - 每次调用
next(jump)时,生成器会根据jump值来修改当前索引,并返回数组中对应的新值。 - 当
startIndex超出数组范围时,可以利用模运算来确保索引始终在有效范围内:startIndex + jump:计算新的索引。(startIndex + jump) % n:模运算确保索引不会超出数组边界。((startIndex + jump) % n + n) % n:如果模运算结果为负数(例如-1),则加上n后再取模,确保索引非负。
复杂度分析
- 时间复杂度: 每次调用
next(jump)的操作是O(1),因为只是做了简单的索引计算和模运算。 - 空间复杂度:
O(1),生成器只维护一个索引,没有额外的空间开销。
代码
/**
* @param {Array} arr
* @param {number} startIndex
* @return {Generator<number>}
*/
var cycleGenerator = function* (arr, startIndex) {
const n = arr.length;
while (true) {
// 返回当前索引的元素
const jump = yield arr[startIndex];
// 根据 jump 更新索引,并使用模运算确保其在合法范围内
startIndex = (((startIndex + jump) % n) + n) % n;
}
};
