- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 F# 中实现一个简单的二进制搜索,作为学习函数式编程的一种方式。我已经在我的主要语言 C# 中以命令式方式实现了它,但我认为通过在 F# 中以递归方式实现它,这将是一个很好的挑战,也是学习函数式概念的好方法。我已经走得够远了,它可以正确地找到值,我的问题是,如果值不在数组中,我希望函数返回 -1,否则返回值的索引,但我想不出来跟踪索引的好方法。这是我的代码:
let rec chop i (nums:array<int>) =
match nums with
| [||] -> -1
| [|x|] -> if x = i then x else -1
| _ ->
let mid = nums.Length / 2 in
if nums.[mid] < i then (chop i nums.[mid..])
elif nums.[mid] > i then (chop i nums.[..mid])
else mid
[<EntryPoint>]
let main argv =
printfn "%d" (chop 20 (Array.init 100 (fun index -> index * 2)))
System.Console.ReadKey() |> ignore
0 // return an integer exit code
由于我每次迭代都会拆分列表,所以当我“向上”移动到数组中时,我会得到不同的索引。在我的示例中,代码返回 3 而不是 10。
推荐的解决方法是什么?任何解决它的方法都值得赞赏,尽管我显然更喜欢在功能意义上这样做的“正确”方法,因为这就是我正在练习的方法。我还想得到任何关于我的解决方案从性能角度来看是否糟糕的建议(例如,首先拆分数组是不是一个坏主意?)
最佳答案
我会更多地使用原件而不复制数组(并使用 Option
而不是魔数(Magic Number) -1
来表示失败):
let chop i (nums : int[]) =
let rec find a b =
if b < a then None else
let mid = (a+b)/2
let midValue = nums.[mid]
if midValue = i then
Some mid
elif i < midValue then
find a (mid-1)
else
find (mid+1) b
find 0 (nums.Length-1)
也许您不喜欢所有这些if
,但这仍然是算法的明显翻译。而且它不会改变或重新分配任何东西。
如果你想删除 ifs 你可以这样做:
let chop i (nums : int[]) =
let rec find a b =
if b < a then None else
let mid = (a+b)/2
match (compare i nums.[mid]) with
| 0 -> Some mid
| -1 -> find a (mid-1)
| 1 -> find (mid+1) b
| _ -> failwith "should never happen"
find 0 (nums.Length-1)
更具可读性(但有点样板化):
[<Literal>]
let Lt = -1
[<Literal>]
let Gt = +1
let chop i (nums : int[]) =
let rec find a b =
if b < a then None else
let mid = (a+b)/2
match (compare i nums.[mid]) with
| Lt -> find a (mid-1)
| Gt -> find (mid+1) b
| Eq -> Some mid
find 0 (nums.Length-1)
(remark 请注意,最后一种情况实际上是所有情况的匹配,我可能应该写成 | _ -> Some mid
但我认为在这种情况下我可能为了可读性而作弊)
就性能而言,您唯一可以改进的是删除递归(但如果启用优化,这应该不是问题)
正如@kvb 正确指出的那样,(a+b)/2
有点冒险(我经常犯这个错误)——所以如果你有非常大的阵列并且想要更安全改用这个:
let mid = a + (b - a) / 2
这当然在数学上是相同的,但对于有限范围和溢出有很大的不同
关于F# BinarySearch 返回位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25922027/
我正在尝试将一个旧项目从使用 ArrayList 集合升级到 List。除了转换 ArrayList.BinarySearch 之外,一切都非常顺利。虽然 List 有相应的方法,但 ArrayLis
问题 我想自己在 Klant 的对象上实现 BinarySearch 方法,我该怎么做?Klant 有一些变量。 public class Klant { public String klantID;
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 5年前关闭。 我是 java 的新程序员,我正在尝试使用 binarySearch
我正在尝试在 F# 中实现一个简单的二进制搜索,作为学习函数式编程的一种方式。我已经在我的主要语言 C# 中以命令式方式实现了它,但我认为通过在 F# 中以递归方式实现它,这将是一个很好的挑战,也是学
我有三个长度为 9 的字符串数组,我想看看它们是否都包含相同的名称。我必须在线性时间 O(NlogN) 内完成此操作。我的计划是对两个数组进行排序,然后使用二进制搜索来查找相似的名称。我的代码就像这样
我使用 xpath 从 xml 文件中填充了一个排序的日期列表(以 dd/mm/yyyy 格式存储为字符串)。 然而,当查询列表以查看列表中是否存在某个日期时,我总是得到否定结果(即不存在),即使我已
我正在开发一个 Java 项目 BinarySearch。我正在尝试创建并初始化一个变量 mid ,它将找出中间值,但它给我一个错误,你不能在这里声明一个变量。我也用 split 声明尝试过,但没有用
我是一名 Java 初学者,我正在尝试编写二进制搜索算法的实现代码。 这是我的代码: protected int doSearch(List list, int key) throws Sea
所以基本上,我知道对有序列表执行二进制搜索只是为了它起作用,所以这是我正在使用的列表: Integer[] x = {1, 2, 3, 4, 5, 6}; 所以基本上它可以找到一个整数,但是当我输入一
正如标题所暗示的,我正在编写一些代码来执行 Java 版本的二分搜索。但是,我的返回语句被忽略,函数反而返回最后一个“捕获所有”返回语句,如下所示: public int binarySear
我应该如何使用二进制搜索来查找排序数组中相邻数字之间的距离是否大于 N?例如: Input: 2 5 8 11 16 Distance: 4 所以我们应该得到邻居之间有这样的距离的答案。 (11 到
所以我想写一个代码来返回键所在的索引,或者如果它不存在,它应该在哪里。我错过了什么?min 为 0,max 为 size - 1,buf 已排序 int binarySearch(string buf
当我尝试编写以下行时: int foundIndex = Collections.binarySearch(keys, key); 它显示错误:参数化方法binarySearch(List>, K)类
function binarySearch(items, target){ var startIndex = 0, stopIndex = items.length-1, middle = Math.
尝试用 Java 编写 Python 风格的 bisect_right,并使用 List 参数的泛型类型: import java.util.*; class Util { /* eqv to
我又遇到了一些关于列表和二进制搜索的问题。一般来说,我有: type TMyArr = array [1..5] of Integer; PMyList = record Com
我正在尝试使用 java.util.Arrays 类的二分搜索(不区分大小写),但它无法搜索指定数组中存在的字符串。以下是程序: package com.test; import java.util.
这不起作用: List byteArrayList = .... ; Collections.binarySearch(byteArrayList, new ByteArrayComparator()
嗨,我正在制作一个程序,该程序采用一系列“术语”,每个术语都有自己的权重(长值)和查询(字符串值)。它应该从 .txt 文件中获取许多术语并将它们初始化为私有(private)“Terms”数组,然后
我很想知道当我使用 Arrays.binarySearch 而不进行排序时得到的答案背后的逻辑是什么。 int d[]={6,-4,12,0,-10}; int x=12; int y=Arrays.
我是一名优秀的程序员,十分优秀!