1、总结
- 我还是有偷懒的概念的,每次实现暴力破解法都跟挤牙膏似的;
- 题目中说至少有三种解决办法,我只写了JavaScript函数和暴力破解法,我记得线性代数中还有关于矩阵的运算方法,但是具体实现已经还给老师了。
数组元素移动K位后的index计算公式:(i+k) % nums.length
do {...} while () 语法
- 这道题要求至少三种解法,可惜的是我只写出来两种偷懒的方法,其实像方法三的一次移动三位,方法四的接力轮询(自己取的名字)等方法,都是有过念头但没有动手实践,
以后做事情,一要上手,二要效率
;
2、题目
Given an array, rotate the array to the right by k steps, where k is non-negative.
Example 1:
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Example 2:
Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation:
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
Could you do it in-place with O(1) extra space?
3、我的解法
方法一:借助JavaScript函数:slice、splice、unshift
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
const tempArr = nums.slice(nums.length-k);
nums.splice(nums.length-k, k)
nums.unshift(...tempArr);
return nums;
};
方法二:暴力破解,循环遍历,按位右移一位
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
if(nums.length > 1) {
for(let i = 0; i < k; i++) {
let tempEnd = nums[nums.length-1];
for(let j = nums.length-1; j >= 0; j--) {
nums[j] = j > 0 ? nums[j-1] : tempEnd;
}
}
}
// return nums;
};
4、其他的解法
方法三:单次循环遍历nums,按位右移K位
这个方法我有想到,但是在取余公式
这里卡住,学习到了;
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
let newArr = [];
for(let i = 0; i < nums.length; i++) {
newArr[(i+k) % nums.length] = nums[i];
}
for(let j = 0; j < nums.length; j++) {
nums[j] = newArr[j];
}
};
方法四:单次循环遍历nums,跳跃移动K位
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
k = k % nums.length; // 注意对 k 的处理
let count = 0;
for(let i = 0; count < nums.length; i++) {
let current = i;
let prev = nums[i];
do {
let next = (current+k)%nums.length;
let temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
count++;
} while (current != i);
}
};
这个算法很好理解,但是实现起来有点纠结,因为需要设置几个中间变量。不过的确省去了方法三重新拷贝数组的时间,所以时间复杂度相对小一点,也不需要一个新的数组来保存数据;
方法五:反转数组
这个反转数组的方法有点线性代数运算的感觉,而且时间复杂度是O(n),空间复杂度是O(1),可以说效率相对较高。
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
function reverse(nums, start, end) {
while(start < end) {
let temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
var rotate = function(nums, k) {
k = k % nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
};