编程挑战系列-奇数偶数找不同

Posted by 咖啡狼 on 2019-07-12

codewar上看到的题目,挑战的题目是:

从一堆数中找到唯一一个奇数或偶数,并告知他的排位(1打头)
’1 2 4 6‘ => 1
‘2 2 1 2 2 4 8’ => 3
’1 3 5 7 8’ => 5


题目简单,答案却依然可分三六九等

初级程序员的方案

1
2
3
4
5
6
7
8
function iqTest(numbers){
numbers = numbers.split(" ").map(function(el){return parseInt(el)});

var odd = numbers.filter(function(el){ return el % 2 === 1});
var even = numbers.filter(function(el){ return el % 2 === 0});

return odd.length < even.length ? (numbers.indexOf(odd[0]) + 1) : (numbers.indexOf(even[0]) + 1);
}

这个方案得票很高,非常的直观,但是效率恐怕?

  1. 使用了模运算判断奇偶数
  2. filter执行了两次

中级程序员的方案

1
2
3
4
5
6
7
function iqTest(numbers){
var even = [], odd = [];
numbers.split(" ").map((num, idx) => {
num & 1 ? odd.push(idx): even.push(idx)
})
return (even.length === 1 ? even[0] : odd[0]) + 1
}

这个方案好多了,不仅减少了一次循环,而且使用位运算判断奇数偶数。

高级程序员的方案

哪里还能优化呢? 考虑一组数有1000000个,第一个是奇数,其余都是偶数。还需要循环全部的数吗?

1
2
3
4
5
6
7
8
9
10
function iqTest(numbers){  
numbers = numbers.split(' ');
var bitsum = ( (numbers[0] & 1) + (numbers[1] & 1) + (numbers[2] & 1) );
var needle = (bitsum < 2) ? 1 : 0;
for(var i=0; i<numbers.length; i++){
if ((numbers[i] & 1) == needle){
return i+1;
}
}
}

我的方案

性能还好,简洁性就差了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function isEven(num)
{
return (num & 1) === 0;
}
function iqTest(numbers){
// ...
let lastEvenIdx = 0;
let lastOddIdx = 0;
let evencnt =0;
let oddcnt =0;
let numarr = numbers.split(' ');

for(let i=0;i<numarr.length;i++)
{
if(isEven(Number(numarr[i])))
{
evencnt ++;
lastEvenIdx = i+1;
}
else
{
oddcnt ++;
lastOddIdx = i+1;
}

if(evencnt >= 2 && oddcnt > 0)
return lastOddIdx;
else if(oddcnt >=2 && evencnt > 0)
return lastEvenIdx;
}
return 0;
}

其他有趣的方案

利用正则表达式

1
2
3
4
function iqTest(numbers){
var m = numbers.match(/[02468]\b.*[02468]\b/.test(numbers) ? /\d*[13579]\b/ : /\d*[02468]\b/)[0];
return numbers.split(' ').indexOf(m) + 1;
}

你有更好的方案吗?