例如:给定一个数组:
var a = [5,4,3,2,1,4,5,6,7,1];
预期总和为:3 + 2 + 6 + 7 = 18
整个代码中应该只有一个for循环。
我失败的方法:
var a = [1,1,1,2,2,2,3,4,5,6,7,7,8,2]
var expected = 3+4+5+6+8
const sum1 = (a) => {
var s = 0;
var ch = {};
for(let i = 0; i<a.length; i++) {
if(s <0) {
s = 0;
}
if(ch[a[i]]) {
s -= a[i]
} else {
ch[a[i]] = a[i];
s += a[i];
}
}
return s
}
console.log(sum1(a))
答案 0 :(得分:2)
在每次迭代中,将要迭代的数字加到总和上。使用Set来跟踪到目前为止已出现的数字。如果之前一次看到过该数字,则将其从总和中减去(这样就好像该数字从未被添加到总和中一样)。如果被发现两次或更多次,请忽略它,因为已经从总和中减去了它:
const sumUniques = (input) => {
let sum = 0;
// duplicates get put into seenOnce
// and subtracted from the sum
const seenOnce = new Set();
// duplicates in seenTwice get completely ignored;
// they've already been subtracted from the sum
const seenTwice = new Set();
input.forEach((num) => {
if (seenTwice.has(num)) {
return;
}
if (seenOnce.has(num)) {
sum -= num;
seenTwice.add(num);
} else {
sum += num;
seenOnce.add(num);
}
});
return sum;
}
console.log(sumUniques([5,4,3,2,1,4,5,6,7,1]))
console.log(sumUniques([1,1,1,2,2,2,3,4,5,6,7,7,8,2]))
答案 1 :(得分:2)
这是一个使用映射的解决方案,其中键是元素,值是遇到元素的次数的计数。
const sum = array => {
const map = new Map();
return array.reduce((sum, e) => {
const seenCount = (map.get(e) || 0) + 1;
map.set(e, seenCount);
if (seenCount === 1) {
sum += e;
} else if (seenCount === 2) {
sum -= e;
}
return sum;
}, 0);
}
答案 2 :(得分:1)
Java解决方案
public static void main(String[] args) {
int[] arr = {5,4,3,2,1,4,5,6,7,1,5};
int sum = 0;
Set<Integer> list = new HashSet<>();
Set<Integer> doneList = new HashSet<>();
for (int i = 0; i < arr.length; i++) {
if(doneList.contains(arr[i])) continue;
if (!list.contains(arr[i])) {
list.add(arr[i]);
sum += arr[i];
} else{
sum -= arr[i];
doneList.add(arr[i]);
}
}
System.out.println(sum);
}