直接上代码:
在 node 环境中,交换1能够执行,交换2会陷入死循环
并且按照百度上的操作,进行添加括号,或者是添加分号都无法通过交换2正常执行代码
这是为什么?
function minNum (nums) {
let result = nums.length + 1
for ( let i = 0; i < nums.length; i++) {
// console.log(nums[i] !== nums[nums[i] - 1]);
const judge = nums[i] >= 1 && (nums[i] <= nums.length) && (nums[i] !== nums[nums[i] - 1])
if (judge) {
// 交换1
const temp = nums[nums[i] - 1];
nums[nums[i] - 1] = nums[i];
nums[i] = temp;
// 交换2
// [nums[i], nums[nums[i] - 1]] = [nums[nums[i] - 1], nums[i]]
// console.log('柳树');
i -= 1
}
}
console.log(nums);
for (let i = 0; i < nums.length; i++) {
if (i+1 < nums[i]) {
return i + 1
}
}
return result
}
const res = minNum([7, 2, 6, 1, 8, 9, 11, 12])
console.log(res);
(ps:这是一道面试题,求数组中未出现的最小正整数,要求时间复杂度为O(n))
这跟循环无关,是解构交换的问题。一般情况下解构交换是没有问题的,但是从这里发生的现象来看
[nums[i], nums[nums[i] - 1]] = [nums[nums[i] - 1], nums[i]]
这句话的执行顺序貌似是(在i == 0
时)nums[i] = nums[nums[i] - 1]
,即nums[i] = nums[7 - 1] = 11
nums[nums[i] - 1] = nums[i]
,按理说应该是nums[7 - 1] = nums[0] = 7
,但它算成了nums[11 - 1] = nums[0] = 7
,即nums[10] = 7
,结果得到了[ 11, 2, 6, 1, 8, 9, 11, 12, <2 empty items>, 7 ]
为什么会这样,确实有点想不通,所以用 Proxy 写了个代理来跟踪了一下:
得到这样一个结果:
注意到倒数第 2 行是重新对索引 0 取了值的。
再尝试,如果直接用固定索引交换,是这样
并没有重新取值。
所以猜测:由于计算过程中检测到
nums[0]
发生了变化,所以重新进行了一次get
,造成了上面的结果。至于为什么会这样,可能需要从 ECMAScript-262 Specification 中去找答案了。补充,把交换的两个对象交换了一下位置
输出
在
set 6
之前也重新get
了一次。所以应该不是因为num[0]
发生了变化才重新取值的,而是在对nums[nums[i] - 1]
赋值之前一定会计算一下nums[i]
。这么说来,之前是想复杂了。实事就是,先计算等号右边的值,然后对等号左边的变量依次赋值。如果需要计算(比如计算索引)就依次先计算,再赋值。