在数组中查找第一个副本并返回最小索引

时间:2017-07-21 19:18:08

标签: javascript algorithm

所以问题是:

  

给定一个仅包含1到a.length范围内的数字的数组a,找到第二个匹配项具有最小索引的第一个重复数字。换句话说,如果有多于1个重复的数字,则返回第二次出现的索引小于另一个出现的第二次出现的索引的数量。如果没有这样的元素,则返回-1。   编写具有O(n)时间复杂度和O(1)额外空间复杂度的解决方案。

我有一个解决方案,但显然它不够快,并且当阵列中有超过一千个项目时会停止。

这就是我所拥有的:

function firstDuplicate(arr) {
  let dictionary = {};

  for(let i = 0, ii = arr.length; i < ii; i++) {
    for(let z = i+1, zz = arr.length; z < zz; z++) {
      if(arr[i] === arr[z]) {
        if(dictionary.hasOwnProperty(arr[i])) {
          if(dictionary[arr[i]] !== 0 && dictionary[arr[i]] > z) {
            dictionary[i] = z;
          }
        } else {
          dictionary[arr[i]] = z;
        }
      }
    }
  }

  let answer = [];

  for(key in dictionary) {
    // [array number, position];
    answer.push([key, dictionary[key]]);
  };

if(answer.length > 0) {
  return Number(answer.sort((a, b) => {
    return a[1]-b[1];
  })[0][0]);
}

return -1;
}

我认为将对象转换为数组然后在答案完成后对数组进行排序会降低整个函数的速度。使用内置的JS方法,如forEachmapsort(就像我上面所做的那样),可以进一步减慢代码/功能。显然有一种更好,更准确的方法,所以我要求一些JS主谋帮我解决这个问题。

5 个答案:

答案 0 :(得分:5)

您可以继续将数字添加到字典中作为带有值作为索引的键,并且只要在字典中找到重复键,就会返回其值。这将是O(n)时间复杂度和O(n)空间复杂度。

function firstDuplicate(arr) {
  var dictionary = {};

  for(var i = 0; i < arr.length; i++) {
if(dictionary[arr[i]] !== undefined)
     return arr[i];
else
   dictionary[arr[i]] = i;
  }

  return -1;
}

console.log(firstDuplicate([2, 3, 3, 1, 5, 2]));

由于数字在1到arr.length之间,您可以迭代数组。对于每个arr [i]使用arr [i]作为索引并使元素存在并且arr [arr [i]]为负,则第一个arr [arr [i]]负返回arr [i]。这给出了O(1)空间复杂度和O(n)时间复杂度,你可以这样做:

function firstDuplicate(arr) {

  for(var i = 0; i < arr.length; i++) {
if(arr[Math.abs(arr[i])] < 0)
     return Math.abs(arr[i]);
else
   arr[Math.abs(arr[i])] = 0 - arr[Math.abs(arr[i])];
  }

  return -1;
}

console.log(firstDuplicate([2, 3, 3, 1, 5, 2]));

答案 1 :(得分:1)

function firstDuplicate(arr) {
   for(var i = 0; i < arr.length; i++) {
        var num = Math.abs(arr[i]);
        if(arr[num] < 0)
            return num;
        arr[num] = - arr[num];
    }
    return -1;
} 
console.log(firstDuplicate([2,2,3,1,2]));

答案 2 :(得分:1)

@dij提到的答案很好,但[2,2]或[2,3,3]会失败, 一点变化 对于输入[2,2],i = 0我们得到[Math.abs [a [0]] = a [2] = undefined 所以我们从[Math.abs [a [0] -1]中删除1,这将立即起作用

function firstDuplicate(arr) {

  for(var i = 0; i < arr.length; i++) {
    if(arr[Math.abs(arr[i])-1] < 0)
      return Math.abs(arr[i]);
    else
      arr[Math.abs(arr[i])-1] = 0 - arr[Math.abs(arr[i])-1];
   }

   return -1;
}

答案 3 :(得分:0)

select name,date,time from
(select name from table order by concat(date,' ',time) ASC)
as sorted limit 10

答案 4 :(得分:0)

请尝试以下代码:

function getCountOccurence(A) {

    let result = [];
    A.forEach(elem => {
        if (result.length > 0) {
            let isOccure = false;
            result.some((element) => {
                if (element.element == elem) {
                    element.count++;
                    isOccure = true;
                }
            });
            if (!isOccure) {
                result.push({element: elem, count: 1});
            }
        } else {
            result.push({element: elem, count: 1});
        }
    });
    return result;
}

function getFirstRepeatingElement(A) {

    let array = getCountOccurence(A);
    array.some((element)=> {
        if (element.count > 1) {
            result = element.element;
            return true;
        }
    });
    return result;
}