我遇到了下面的面试问题及其解决方案,我很难弄清楚它的工作原理:
给出一个排序的数组nums,就地删除重复项,这样 每个元素仅出现一次并返回新的长度。不要 为另一个数组分配额外的空间,您必须通过修改 输入数组就位,并具有O(1)个额外的内存。
下面是解决方案。有人可以向我解释一下这是如何工作的吗?我无法理解以下算法,而且如果我取消注释system.out行,那么它将引发异常,因此对于nums[i - 1]
的情况,i=0
在if块中如何工作?
public static int removeDuplicatess(int[] nums) {
int i = 0;
for (int n : nums) {
// System.out.println(nums[i - 1]);
if (i == 0 || n > nums[i - 1])
nums[i++] = n;
}
return i;
}
答案 0 :(得分:2)
此方法遍历Array
中的每个数字。它首先在Array
中添加第一个数字,因为它不可能是重复的,因为它是第一个数字。 (这是i == 0
的{{1}}部分的用途。然后它向后看一个索引以查看是否if
。只有{{1} }不是重复的,因为列表是排序的。如果是这种情况,则将其添加到n > nums[i - 1]
中。
n
在第一次迭代中:
Array
[0, 1, 1, 3]
n == 0
计算为true。 i == 0
被添加到索引i == 0
。 第二次迭代:
0
0
n == 1
(1> i == 1
)计算为true,n > nums[i - 1]
被添加到0
第三次迭代:
1
Array
n == 1
(1> 1)的取值为i == 2
,因此{em> not 不添加n > nums[i - 1]
到false
第四次迭代:
1
Array
n == 3
(3> 1)的值为i == 2
,并且n > nums[i - 1]
被添加到true
。如果我取消注释system.out行,那么它将引发异常,因此在i = 0的情况下,nums [i-1]如何在if块中工作?
这是因为3
是短路操作。这意味着,如果一侧评估为true,则另一侧将不会评估。因此,在Array
:
||
然后您呼叫i == 0
,(将if (i == 0 || n > nums[i - 1])
^^^^^^--- Evaluates to true. num[i-1] is not considered
nums[i++] = n;
放入nums[i++]
后,i
会递增),它将变成n
1。然后您将呼叫nums[i]
,将是有效的索引i
。
答案 1 :(得分:1)
您迭代数组中的所有数字。由于该数组已经排序,因此每个循环变量n都将大于或等于最后一个。
第一个数字(大小写i==0
)总是出现在结果中(因为单个数字不能重复)。
此后,只需检查当前观察到的数字是否大于我们决定保留的最后一个数字(如果小于,则不对您的数组进行排序,并且算法会中断;如果相等,则它是重复的)并编写它到第i + 1个位置的数组。
答案 2 :(得分:1)
/*toBeTested.js*/
const getAuthenticationInfo = (orgId) => {
return "TEST";};
const getAuthToken = (orgId) => { var lmsInfo = getAuthenticationInfo(orgId);
return lmsInfo;
}
module.exports = {
getAuthenticationInfo,
getAuthToken
}
/*api-test.js*/
const sinon = require('sinon');
const toBeTested = require('./toBeTested');
sinon.stub(toBeTested,"getAuthenticationInfo").returns("mocked-response");
console.log(toBeTested.getAuthInfo());
之所以有效,是因为简短地评估了复杂的逻辑表达式-当第一项nums[i - 1]
为真时,就无需评估第二项(对于逻辑i == 0
条款之间的操作)。
算法的逻辑是简单明了的-如果当前值与先前的值相同-则将其忽略,否则将其写入数组的压缩起始部分。