Skip to content

Commit 681575b

Browse files
author
oushihao
committed
feat(rotate-array): 使用额外的数组 | 环形替换 | 数组翻转
1 parent 96a3d00 commit 681575b

File tree

7 files changed

+219
-0
lines changed

7 files changed

+219
-0
lines changed

assets/data/category.json

+6
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,12 @@
10791079
"path": "../../problemset/compare-version-numbers/README.md",
10801080
"difficulty": "中等"
10811081
},
1082+
{
1083+
"id": 189,
1084+
"title": "轮转数组",
1085+
"path": "../../problemset/rotate-array/README.md",
1086+
"difficulty": "中等"
1087+
},
10821088
{
10831089
"id": 258,
10841090
"title": "各位相加",

assets/data/problems.json

+10
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,16 @@
16991699
"url": "https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/",
17001700
"path": "../../problemset/best-time-to-buy-and-sell-stock-4/README.md"
17011701
},
1702+
{
1703+
"id": 189,
1704+
"title": {
1705+
"cn": "轮转数组",
1706+
"en": "rotate-array"
1707+
},
1708+
"difficulty": "中等",
1709+
"url": "https://leetcode-cn.com/problems/rotate-array/",
1710+
"path": "../../problemset/rotate-array/README.md"
1711+
},
17021712
{
17031713
"id": 258,
17041714
"title": {

assets/docs/CATEGORY.md

+1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@
221221
| 134. [加油站](../../problemset/gas-station/README.md) | 中等 |
222222
| 135. [分发糖果](../../problemset/candy/README.md) | 困难 |
223223
| 165. [比较版本号](../../problemset/compare-version-numbers/README.md) | 中等 |
224+
| 189. [轮转数组](../../problemset/rotate-array/README.md) | 中等 |
224225
| 258. [各位相加](../../problemset/add-digits/README.md) | 简单 |
225226
| 393. [UTF-8 编码验证](../../problemset/utf-8-validation/README.md) | 中等 |
226227
| 521. [最长特殊序列](../../problemset/longest-uncommon-subsequence/README.md) | 简单 |

assets/docs/PROBLEMS.md

+2
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@
340340

341341
[188. 买卖股票的最佳时机 IV](../../problemset/best-time-to-buy-and-sell-stock-4/README.md)
342342

343+
[189. 轮转数组](../../problemset/rotate-array/README.md)
344+
343345
[258. 各位相加](../../problemset/add-digits/README.md)
344346

345347
[300. 最长递增子序列](../../problemset/longest-increasing-subsequence/README.md)

problemset/rotate-array/README.md

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# 轮转数组
2+
3+
> 难度:中等
4+
>
5+
> https://leetcode-cn.com/problems/rotate-array/
6+
7+
## 题目
8+
9+
给你一个数组,将数组中的元素向右轮转 `k`  个位置,其中  `k` 是非负数。
10+
11+
### 示例
12+
13+
#### 示例 1:
14+
15+
```
16+
输入: nums = [1,2,3,4,5,6,7], k = 3
17+
输出: [5,6,7,1,2,3,4]
18+
解释:
19+
向右轮转 1 步: [7,1,2,3,4,5,6]
20+
向右轮转 2 步: [6,7,1,2,3,4,5]
21+
向右轮转 3 步: [5,6,7,1,2,3,4]
22+
```
23+
24+
#### 示例  2:
25+
26+
```
27+
输入:nums = [-1,-100,3,99], k = 2
28+
输出:[3,99,-1,-100]
29+
解释:
30+
向右轮转 1 步: [99,-1,-100,3]
31+
向右轮转 2 步: [3,99,-1,-100]
32+
```
33+
34+
## 解题
35+
36+
### 使用额外的数组
37+
38+
```typescript
39+
/**
40+
* 使用额外的数组
41+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
42+
* @param nums
43+
* @param k
44+
*/
45+
export function rotate(nums: number[], k: number): void {
46+
if ((k = k % nums.length) && k === 0) return;
47+
nums.unshift(...nums.splice(nums.length - k));
48+
}
49+
```
50+
51+
### 环形替换
52+
53+
```typescript
54+
/**
55+
* 环形替换
56+
* @desc 时间复杂度 O(N) 空间复杂度 O(1)
57+
* @param nums
58+
* @param k
59+
*/
60+
export function rotate2(nums: number[], k: number): void {
61+
const len = nums.length;
62+
if ((k = k % len) && k === 0) return;
63+
64+
// 求最大公约数
65+
const gcd = (x: number, y: number): number => (y ? gcd(y, x % y) : x);
66+
// 遍历的次数
67+
const count = gcd(k, len);
68+
69+
for (let start = 0; start < count; start++) {
70+
let current = start;
71+
let prev = nums[start];
72+
73+
// nums[i] < nums-> nums[(i+k)%len]
74+
do {
75+
const next = (current + k) % len;
76+
[nums[next], prev] = [prev, nums[next]];
77+
current = next;
78+
} while (start !== current);
79+
}
80+
}
81+
```
82+
83+
### 数组翻转
84+
85+
```typescript
86+
/**
87+
* 数组翻转
88+
* @desc 时间复杂度 O(N) 空间复杂度 O(1)
89+
* @param nums
90+
* @param k
91+
*/
92+
export function rotate3(nums: number[], k: number): void {
93+
const len = nums.length;
94+
if ((k = k % len) && k === 0) return;
95+
reverse(nums, 0, len - 1);
96+
reverse(nums, 0, k - 1);
97+
reverse(nums, k, len - 1);
98+
99+
function reverse(nums: number[], start: number, end: number) {
100+
while (start < end) {
101+
[nums[start], nums[end]] = [nums[end], nums[start]];
102+
start++;
103+
end--;
104+
}
105+
}
106+
}
107+
```

problemset/rotate-array/index.spec.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { rotate, rotate2, rotate3 } from '.';
2+
3+
describe('轮转数组', () => {
4+
describe('使用额外的数组', () => {
5+
testCase(rotate);
6+
});
7+
8+
describe('环形替换', () => {
9+
testCase(rotate2);
10+
});
11+
12+
describe('数组翻转', () => {
13+
testCase(rotate3);
14+
});
15+
});
16+
17+
function testCase(fn: (nums: number[], k: number) => void) {
18+
it('示例一', () => {
19+
const nums = [1, 2, 3, 4, 5, 6, 7];
20+
const k = 3;
21+
fn(nums, k);
22+
23+
expect(nums).toStrictEqual([5, 6, 7, 1, 2, 3, 4]);
24+
});
25+
26+
it('示例二', () => {
27+
const nums = [-1, -100, 3, 99];
28+
const k = 2;
29+
fn(nums, k);
30+
31+
expect(nums).toStrictEqual([3, 99, -1, -100]);
32+
});
33+
}

problemset/rotate-array/index.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* 使用额外的数组
3+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
4+
* @param nums
5+
* @param k
6+
*/
7+
export function rotate(nums: number[], k: number): void {
8+
if ((k = k % nums.length) && k === 0) return;
9+
nums.unshift(...nums.splice(nums.length - k));
10+
}
11+
12+
/**
13+
* 环形替换
14+
* @desc 时间复杂度 O(N) 空间复杂度 O(1)
15+
* @param nums
16+
* @param k
17+
*/
18+
export function rotate2(nums: number[], k: number): void {
19+
const len = nums.length;
20+
if ((k = k % len) && k === 0) return;
21+
22+
// 求最大公约数
23+
const gcd = (x: number, y: number): number => (y ? gcd(y, x % y) : x);
24+
// 遍历的次数
25+
const count = gcd(k, len);
26+
27+
for (let start = 0; start < count; start++) {
28+
let current = start;
29+
let prev = nums[start];
30+
31+
// nums[i] < nums-> nums[(i+k)%len]
32+
do {
33+
const next = (current + k) % len;
34+
[nums[next], prev] = [prev, nums[next]];
35+
current = next;
36+
} while (start !== current);
37+
}
38+
}
39+
40+
/**
41+
* 数组翻转
42+
* @desc 时间复杂度 O(N) 空间复杂度 O(1)
43+
* @param nums
44+
* @param k
45+
*/
46+
export function rotate3(nums: number[], k: number): void {
47+
const len = nums.length;
48+
if ((k = k % len) && k === 0) return;
49+
reverse(nums, 0, len - 1);
50+
reverse(nums, 0, k - 1);
51+
reverse(nums, k, len - 1);
52+
53+
function reverse(nums: number[], start: number, end: number) {
54+
while (start < end) {
55+
[nums[start], nums[end]] = [nums[end], nums[start]];
56+
start++;
57+
end--;
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)