arrays - 如何使我的 ruby​​ remove_duplicates(nums) 算法更高效

标签 arrays ruby algorithm

这是编码挑战:给定一个排序数组,就地删除重复项,使每个元素只出现一次并返回新长度。

不要为另一个数组分配额外空间,您必须通过使用 O(1) 额外内存就地修改输入数组来执行此操作。

我的回答

def remove_duplicates(nums)

    hash = {}

    nums.each do |num|
      if hash[num].nil?
        hash[num] = 1
      end 
      if hash[num] = 1
        i = nums.index(num)
        nums.delete(num)
        nums.insert(i, num)
      end 
    end

    nums.length    
end

在 leetcode 上,我的答案通过了 160/161 个测试用例。但我收到“超出时间限制”错误。该错误表明我的回答不够有效,无法解决最后一个测试用例。

我是初学者,我正在寻找有关如何使我的回答更有效率的建议(在 ruby​​ 中)!

最佳答案

如果您不想使用评论中建议的内置方法之一,在 O(n) 时间和 O(1) 空间中执行此操作的一种算法是使用 2 个索引循环遍历大批。第一个将是您上次插入唯一值的索引,第二个是您当前正在查看的元素的索引。这样做的关键是 nums 数组是排序的,所以你只需要设置下一个值,如果它大于当前值。它不能小于(因为已排序)并且如果它等于您插入的最后一个值,则它不是唯一的。例如:

nums = [1, 1, 1, 2, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 8, 8, 9, 10, 10]
def remove_duplicates(nums)
  return 0 if !nums || nums.empty?
  insertion_index = 0

  1.upto(nums.length - 1) do |lookup_index|
    if nums[lookup_index] > nums[insertion_index]
      insertion_index += 1

      nums[insertion_index] = nums[lookup_index]
    end
  end

  # nums is currently:
  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5, 5, 6, 7, 8, 8, 9, 10, 10]
  insertion_index + 1
end

remove_duplicates(nums)

您的返回值将是 insertion_index + 1,因为 insertion_index 是插入最后一个唯一值的索引,所以数组的长度是最终索引 + 1。

自从我完成一个 leetcode 问题已经有一段时间了,但我似乎记得在这样的问题中,你需要在适当的位置调整数组的大小,只是把所有的东西都留在最后,不管是什么方法(我们在 Ruby 中,但有很多其他语言的提交,其中只调整数组大小并不容易)。如果您愿意/但如果您只需要唯一数组的长度,则可以随意从末尾删除值(根据说明就地删除),则没有必要这样做。

关于arrays - 如何使我的 ruby​​ remove_duplicates(nums) 算法更高效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47805307/

相关文章:

arrays - Fortran 用户定义运算符中未分配的假定形状数组的问题

python - 如何使用python将数组中的字符串切片到另一个数组中

ruby - 使用 Ruby 和 FFI 获取 PID

ruby - Array#split 超出数组边界访问时的行为

java - for 循环 - 在最后一次迭代中,术语无法正常工作

javascript - inArray() 一直返回 false

将字符串数组转换为 C 中的十六进制数

ruby-on-rails - pg.rb 段错误 [Mojave 升级]

algorithm - 根据 map 中的第二个值进行搜索

algorithm - 在不使用 + 和 - 运算符的情况下添加两个数字