地点:https://leetcode.com/problems/move-zeroes/
运用场景申明
这个题是很Easy的一道题,它的运用场景是在我尝试写小游戏2048时,采纳了二维数组寄存数字占位,当按上下左右键时,要把一切的数字靠在一边,而一切为0的靠在另一边,这时候刻用到这个题的解题思绪很快能做出来。
解法
目标就是把一个数组中一切为0的数移动到数组的尾部,并保证其他元素相对位置稳定。要求是在原数组上修正,不要分外引入其他的数组;只管削减操纵次数。
输入:
[0,1,0,3,12]
输出
[1,3,12,0,0]
起首先引入分外数组的体式格局看怎样来写:
var moveZeroes = function(nums) {
let nonZeroArr = []; // 用来寄存非0元素
for(let i = 0; i < nums.length; i++) {
if(nums[i]){
nonZeroArr.push(nums[i])
}
}
// 把新数组中的每一项对位的赋值给原数组
for(let j = 0; j < nonZeroArr.length; j++){
nums[j] = nonZeroArr[j]
}
// 把nums中以后的位置都补上0
for(let k = nonZeroArr.length; k < nums.length; k++){
nums[k] = 0;
}
return nums;
};
let arr = [0,1,0,3,0,9,0,12];
console.log(moveZeroes(arr)); // [ 1, 3, 9, 12, 0, 0, 0, 0 ]
思绪很简朴,就是把不为0的数字存在一个新数组中,把新数组的每一项对位的从新赋值给本来数组的位置,然后把原数组盈余的位置一概替代为0;
如许的写法在时刻庞杂度上是 O(n) 级别的,在空间庞杂度上也是O(n) 级别的,由于引入了新的数组。
能够在不引入新数组的情况下做位置的调解:
var moveZeroes = function(nums) {
let lastZeroIndex = 0; // 每一次末了找到的0的位置,初始是0
for(let i = 0; i < nums.length; i++){
if(nums[i]) { // 不为0
nums[lastZeroIndex++] = nums[i]; // 把遍历到不为0的数字,替代在0的位置,替代的位置已不是0了,向后推一步;
}
}
// 从k的位置最先以后的都应该为0
while(lastZeroIndex < nums.length){
nums[lastZeroIndex++] = 0;
}
return nums;
};
let arr = [0,1,0,3,0,9,0,12];
console.log(moveZeroes(arr)); // [ 1, 3, 9, 12, 0, 0, 0, 0 ]
以上的做法只在一个数组中操纵,用变量 repalceIndex 存一下要被非零数字替代的位置。在遍历中碰到了非0数字,则替代在 repalceIndex的位置,再将repalceIndex向后推一名,守候下一次碰到非零数字来替代,比及遍历完毕,repalceIndex 实际上就黑白零数字的个数,再从这个位置最先直到数组完毕都替代为0。
如许的写法在时刻庞杂度上是 O(n) 级别的,在空间庞杂度上也是O(1) 级别的,由于没有引入了新的数组。
如许还不是终究答案,由于在末了还需要一个 for 轮回将剩下的位置都替代为0,多了一步如许的操纵是没必要的。
下面采纳交流位置的体式格局。
var moveZeroes = function(nums) {
let repalceIndex = 0; // 纪录要被交流的位置
let replaceElement; // 中心变量,用来存不为0的数字
for(let i = 0; i < nums.length; i++){
if(nums[i]) { // 当不为0
if(i != repalceIndex) { // 第i个和repalceIndex雷同,申明要交流的是同一个元素,没必要举行交流操纵
replaceElement = nums[i];
nums[i] = 0;
nums[repalceIndex] = replaceElement;
}
repalceIndex++
}
}
return nums;
};
let arr = [0,1,0,3,0,9,0,12];
console.log(moveZeroes(arr)); // [ 1, 3, 9, 12, 0, 0, 0, 0 ]
上面的思绪是如许的,repalceIndex 纪录了第一个是0的位置,当碰到非0的数字时刻,就把非0的数字和repalceIndex所在位置的0交流位置,然后 repalceIndex 向前推动一名,继承纪录的照样第一个0的位置,遍历中再与非0数字交流,再推动。。。反复这个历程直到遍历完毕。
推断 i != repalceIndex 是一种优化手腕,只需非0位置的数字和要交流的位置不是同一个位置才举行交流。
我本身在写小游戏2048的时刻用到了这个题的解题思绪。在小游戏2048中,设置了和界面一致的二维数组,数组的每一名纪录了一个数字。
尝试用在小游戏2048中
我在写2048小游戏时,数据寄存的是一个 4X4 的二维数组(当然有许多的做法,能够采纳别的体式格局),比方如许:
let data = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
这些0都是占位的,代表的是还未添补任何数据,跟着玩家玩的历程,会涌现许多数字疏散在差别的位置上,当按上下左右时,总要把一切不为0的数字拨在同一边,0的数字在另一边,这时候就用到上述这个题的解法即可。
let data = [
[2, 0, 0, 0],
[0, 4, 0, 0],
[0, 0, 2, 4],
[0, 2, 2, 0]
]
// 遍历掏出每个数组
for(let i = 0; i < data.length; i++){
moveZeroes(data[i])
}
假如控制了上述的技能,无论是向左向右照样向上向下都能够做到。
跋文
在刚最先尝试解这道题时,内心在想,出这道题的人是有多无聊,只是为了制造题目而制造,压根想不到这道题的运用场景在那里,这也跟本身的眼界有关联。当我在尝试做2048小游戏时,设想出来寄存数据结构后,最先完成本身要完成的体式格局时,才意想到本来这么简朴的一道题不是没有场景,而是本身没碰到,当碰到时恍然大悟。
这也给了我一个启发,任何一道题存在必定是有缘由的,它就是处理了某一个题目而存在的,当我有了如许的认识,在做每一道题的时刻,会多问本身一下,这道题的运用场景在那里,我如今做的项目中有没有相似的场景能够套用,假如没有,去找一种案例运用在场景中,如许刷完提后不至于很快遗忘,只需记着了案例,刷的题也自然而然的记着了。
以上若有误差迎接斧正进修,感谢。