- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
问题是:找到 nums[index1] + nums[index2] == target
两个数字的索引。这是我在 golang
中的尝试(索引从 1 开始):
package main
import (
"fmt"
)
var nums = []int{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 25182, 25184, 25186, 25188, 25190, 25192, 25194, 25196} // The number list is too long, I put the whole numbers in a gist: https://gist.github.com/nickleeh/8eedb39e008da8b47864
var target int = 16021
func twoSum(nums []int, target int) (int, int) {
if len(nums) <= 1 {
return 0, 0
}
hdict := make(map[int]int)
for i := 1; i < len(nums); i++ {
if val, ok := hdict[nums[i+1]]; ok {
return val, i + 1
} else {
hdict[target-nums[i+1]] = i + 1
}
}
return 0, 0
}
func main() {
fmt.Println(twoSum(nums, target))
}
nums 列表太长了,我把它归为一个要点: https://gist.github.com/nickleeh/8eedb39e008da8b47864
这段代码工作正常,但我发现 return 0,0
部分很难看,而且它的运行速度比 Julia
翻译慢十倍。我想知道有没有写的很烂影响性能的部分?
编辑:Julia 的翻译:
function two_sum(nums, target)
if length(nums) <= 1
return false
end
hdict = Dict()
for i in 1:length(nums)
if haskey(hdict, nums[i])
return [hdict[nums[i]], i]
else
hdict[target - nums[i]] = i
end
end
end
最佳答案
在我看来,如果没有找到添加到 target
的元素,最好是返回无效索引的值,例如-1
。尽管返回 0, 0
就足够了,因为有效的索引对不能是 2 个相等的索引,但这更方便(因为如果您忘记检查返回值并尝试使用无效的索引,你会立即得到一个运行时 panic ,提醒你不要忘记检查返回值的有效性)。因此,在我的解决方案中,我将摆脱 i + 1
转变,因为它没有意义。
在答案末尾可以找到不同解决方案的基准。
如果 slice 很大且不变,并且您必须多次调用此 twoSum()
函数,最有效的解决方案是简单地使用 sort.Ints()
对数字进行排序。提前:
sort.Ints(nums)
然后你不必构建 map ,你可以使用在sort.SearchInts()
中实现的二进制搜索。 :
func twoSumSorted(nums []int, target int) (int, int) {
for i, v := range nums {
v2 := target - v
if j := sort.SearchInts(nums, v2); v2 == nums[j] {
return i, j
}
}
return -1, -1
}
注意:请注意,排序后,返回的索引将是已排序 slice 中值的索引。这可能与原始(未排序的) slice 中的索引不同(这可能是也可能不是问题)。如果您确实需要原始顺序(原始的、未排序的 slice )的索引,您可以存储已排序和未排序的索引映射,以便您可以获得原始索引。有关详细信息,请参阅此问题:
Get the indices of the array after sorting in golang
这是您摆脱 i + 1
转变的解决方案,因为它毫无意义。 slice 和数组索引在所有语言中都是从零开始的。还利用 for ... range
:
func twoSum(nums []int, target int) (int, int) {
if len(nums) <= 1 {
return -1, -1
}
m := make(map[int]int)
for i, v := range nums {
if j, ok := m[v]; ok {
return j, i
}
m[target-v] = i
}
return -1, -1
}
如果 nums
slice 很大并且没有快速找到解决方案(意味着 i
索引变大)这意味着很多元素将被添加到 map 中. map 从小容量开始,如果需要额外空间来容纳许多元素(键值对),它们会在内部增长。内部增长需要使用已经添加的元素重新散列和重建。这是“非常”昂贵的。
它看起来并不重要,但它确实很重要。由于您知道最终将出现在 map 中的最大元素(最坏情况是 len(nums)
),因此您可以创建一个容量足够大的 map 来容纳最坏情况下的所有元素。好处是不需要内部增长和重新散列。创建 map
时,您可以将初始容量作为第二个参数提供给 make()
。如果 nums
很大,这会大大加快 twoSum2()
的速度:
func twoSum2(nums []int, target int) (int, int) {
if len(nums) <= 1 {
return -1, -1
}
m := make(map[int]int, len(nums))
for i, v := range nums {
if j, ok := m[v]; ok {
return j, i
}
m[target-v] = i
}
return -1, -1
}
这里有一些基准测试代码,用于测试 3 个解决方案的执行速度,其中包含您提供的输入 nums
和 target
。请注意,为了测试 twoSumSorted()
,您首先必须对 nums
slice 进行排序。
将其保存到名为 xx_test.go
的文件中,然后使用 go test -bench 运行它。
:
package main
import (
"sort"
"testing"
)
func BenchmarkTwoSum(b *testing.B) {
for i := 0; i < b.N; i++ {
twoSum(nums, target)
}
}
func BenchmarkTwoSum2(b *testing.B) {
for i := 0; i < b.N; i++ {
twoSum2(nums, target)
}
}
func BenchmarkTwoSumSorted(b *testing.B) {
sort.Ints(nums)
b.ResetTimer()
for i := 0; i < b.N; i++ {
twoSumSorted(nums, target)
}
}
输出:
BenchmarkTwoSum-4 1000 1405542 ns/op
BenchmarkTwoSum2-4 2000 722661 ns/op
BenchmarkTwoSumSorted-4 10000000 133 ns/op
如您所见,制作容量足够大的 map 会加快速度:它的运行速度是两倍。
如前所述,如果 nums
可以提前排序,那就是 ~10,000 倍!
关于performance - 戈朗 : Find two number index where the sum of these two numbers equals to target number,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34668537/
我有一个 合作伙伴集合,我正在使用 pymongo 来检索数据 当我使用 MongoDB 查询集合时,我看到以下结果 db.partner.find({'unique_key': 'c89dbe313
嗨,我正在尝试在一个 find 命令中查找所有 js 和 css 文件。我尝试了以下所有方法但徒劳无功: find WebContent -name "*.[jc]ss?" find WebConte
我使用以下 find 命令查找并显示所有具有输入文本模式的文件。 找 。 -type f -print|xargs grep -n "模式" 我有很多项目文件夹,每个文件夹都有自己的名为“Makefi
我在Windows环境中使用Gnuwin32二进制文件。 当我想查找某种类型的文件时(例如PDF),我通常运行: find . -iname '*.pdf' -print 这在任何UNIX系统上均可完
我使用的是 Julia 编程语言,我知道你可以通过以下方式使用 find 函数: a = [ 1 2 3 4 3 5 3 6 7 8 9 3 ] find(a .== 3) 它将返回:3,5,7,12
jsperf's link 我不是 jQuery 专家(甚至不是一个好的用户),我没有研究它的整个源代码(只有一小部分不能帮助我解决这个问题)。 有人可以为我解释一下吗? 最佳答案 这个: $p.fi
我应该如何在 CentOS 7 中修复这个错误? [jalal@goku HW4]$ git clone https://github.com/pathak22/pyflow.git Cloning
是否可以更改传递给 find 中的 exec 的参数?例如,我需要以不同的名称复制文件:*.txt -> *.new.txt现在我正在为两个命令执行此操作: find /root/test -name
我想通过cleartool find 命令找到*.cs 和*.cpp 文件。但它失败了。 cleartool find "M:\test_view\code" -name "*.cs *.cpp"
我正在使用 PyMongo,看到有人建议使用 find()[:] 而不是 find()。很好奇有什么区别? 最佳答案 [:] 制作列表的浅拷贝,因此对对象的引用是相同的。我查看了 Pymongo 文档
我正在处理文件和目录,以在每个目录中查找最近修改的文件。我的代码可以工作,但作为 Ruby 的新手,我无法正确处理错误。 我使用 Find.find 获取递归目录列表,为每个目录调用我自己的函数 ne
/usr/bin/ld: cannot find -ldlib /usr/bin/ld: cannot find -lcblas /usr/bin/ld: cannot find -llapack 在
我有一些数据文件的一系列索引文件,它们基本上采用这种格式 索引文件:asdfg.log.1234.2345.index 数据文件:asdfg.log 这个想法是搜索所有索引文件。如果值 XXXX 出现
我有一个 find我运行以查找名称包含 foo 的文件的命令. 我想跳过 .git目录。下面的命令有效 除了 它打印一个 烦人 .git任何时候它跳过 .git目录: find . ( -name .
我有以下想做的事情: find . -maxdepth 6 \( -name \*.tar.gz -o -name bediskmodel -o -name src -o -name ciao -o
当我在表中查找隐藏字段时,我看到了两个隐藏字段。但是,我想通过 ID 进一步细化这两个字段。我注意到,当我使用“包含”在整个表上使用 find 时,我得到了 2 个字段。但是,如果我对隐藏字段的查找结
我正在使用下面的命令生成文件列表及其 m5sum。问题是某些文件或文件夹的名称中有空格。我将如何处理这些? find -type f -name \* | xargs md5sum 最佳答案 尝试:
我正在使用下面的命令生成文件列表及其 m5sum。问题是某些文件或文件夹的名称中有空格。我将如何处理这些? find -type f -name \* | xargs md5sum 最佳答案 尝试:
我有一个使用正则表达式查找文件的脚本。代码如下: find $dir | grep "$regex" 脚本运行有点慢,我想优化一下。搜索需要一些时间来执行,我想从中获得更好的性能。我试过这种尝试: f
这令人沮丧。我认为问题出在 api 响应返回的对象上。也许它是在字符串中,所以我所做的就是复制“postman”的响应并将其直接粘贴到js上。这样我就可以确定它在对象/数组中。但结果还是同样的错误。
我是一名优秀的程序员,十分优秀!