【问题标题】:Is it a pattern determine what index variable to be used in binary search? [duplicate]它是一种模式确定要在二进制搜索中使用的索引变量吗? [复制]
【发布时间】:2021-10-17 03:33:32
【问题描述】:

在做https://leetcode.com/problems/search-insert-position时。我发现索引变量的组合很难确定。

例如,我们在代码的每一层都有以下组合。

(1)
l = 0 (stable)
r = len; r = len-1; (outbound / inbound)

(2)
loop(l < r); loop(l <= r) (outbound / inbound)

(3)
l = ind+1 (stable)
r = ind; r = ind-1 (include / exclude)

所以现在你有不同的索引变量组合,其中一些正在工作,但如果你改变其中一个,它不会通过所有测试用例

combo 1:
l=0, r=len (outbound); loop(l < r); l=ind+1, r=ind (include); work

combo 2:
l=0, r=len-1 (inbound); loop(l < r); l=ind+1, r=ind (include); !work

combo 3:
l=0, r=len (inbound); loop(l < r); l=ind+1, r=ind-1 (exclude); !work

combo 4:
l=0, r=len (outbound); loop(l < r); l=ind+1, r=ind (include); work

combo 5:
l=0, r=len-1 (inbound); loop(l<=r); l=ind+1, r=ind (include); work

comb 6:
l=0, r=len (outbound); recursive(l<=r); l=ind+1, r=ind (include); work

下面是我玩的代码。其中一些正在工作,而另一些则不工作

// sm: l=0, r=len (outbound); loop(l < r); l=ind+1, r=ind (include); work
var searchInsert = function (ns, tar) {
  let l = 0;
  let r = ns.length; // outbound
  let ind;

  while (l < r) {
    ind = Math.floor((l + r) / 2);

    if (ns[ind] < tar) {
      l = ind + 1;
    } else if (ns[ind] > tar) {
      r = ind;
    } else {
      return ind; // existed
    }
  }

  return l; // insert
};

// sm: l=0, r=len-1 (inbound); loop(l < r); l=ind+1, r=ind (include); !work
var searchInsert = function (ns, tar) {
  let l = 0;
  let r = ns.length - 1; // inbound, cannot insert outbound
  let ind;

  while (l < r) {
    ind = Math.floor((l + r) / 2);

    if (ns[ind] < tar) {
      l = ind + 1;
    } else if (ns[ind] > tar) {
      r = ind;
    } else {
      return ind; // existed
    }
  }

  return l; // insert
};

// sm: l=0, r=len (inbound); loop(l < r); l=ind+1, r=ind-1 (exclude); !work
var searchInsert = function (ns, tar) {
  let l = 0;
  let r = ns.length;
  let ind;

  while (l < r) {
    ind = Math.floor((l + r) / 2);

    if (ns[ind] < tar) {
      l = ind + 1;
    } else if (ns[ind] > tar) {
      r = ind - 1;
    } else {
      return ind; // existed
    }
  }

  return l; // insert
};

// sm: l=0, r=len (outbound); loop(l < r); l=ind+1, r=ind (include); work
var searchInsert = function (ns, tar) {
  let l = 0;
  let r = ns.length;
  let ind;

  while (l < r) {
    ind = Math.floor((l + r) / 2);

    if (ns[ind] < tar) {
      l = ind + 1;
    } else if (ns[ind] > tar) {
      r = ind;
    } else {
      return ind; // existed
    }
  }

  return l; // insert
};

// sm: l=0, r=len-1 (inbound); loop(l<=r); l=ind+1, r=ind (include); work
var searchInsert = function (ns, tar) {
  let l = 0;
  let r = ns.length - 1;
  let ind;

  while (l <= r) {
    ind = Math.floor((l + r) / 2);

    if (ns[ind] < tar) {
      l = ind + 1;
    } else if (ns[ind] > tar) {
      r = ind - 1;
    } else {
      return ind; // existed
    }
  }

  return l; // insert
};

// sm: l=0, r=len (outbound); recurive(l<=r); l=ind+1, r=ind (include); work
var searchInsert = function (ns, tar) {
  let l = 0;
  let r = ns.length;
  return recur(ns, l, r, tar);
};

var recur = function (ns, l, r, tar) {
  if (l >= r) {
    return l;
  }

  const ind = Math.floor((l + r) / 2);

  if (ns[ind] === tar) {
    return ind;
  } else if (ns[ind] < tar) {
    return recur(ns, ind + 1, r, tar);
  } else if (ns[ind] > tar) {
    return recur(ns, l, ind, tar);
  }
};

const ns = [1, 3, 5, 6];
const tar = 5;
const out = searchInsert(ns, tar);
console.log(out);

我的问题是,当您遇到二分搜索问题时?你怎么知道你要使用哪个索引组合?因为它真的取决于问题,线索和错误

【问题讨论】:

  • 为什么你认为combo2不起作用?我在 LeetCode 上试了一下,效果很好。
  • combo 3中,是入站还是出站?我在 LeetCode 上都测试过,都通过了。您是否使用其他方法来测试解决方案?
  • @LearningMathematics [1,3,5,6],7 失败。对于组合 2,您是否复制并粘贴了代码?你用过javascript吗
  • 这能回答你的问题吗? Binary Search algorithm implementations

标签: javascript node.js algorithm binary-search


【解决方案1】:

对于刚开始学习二分搜索的人来说,这是一个非常常见的问题。我将尝试逐个分析您的示例,看看您是否能更好地理解。

改写

先重新表述问题会很有帮助。如果我们设置ns[ns.length]infinity,问题本质上是要求你找到第一个i,这样ns[i] &gt;= tar

想法

考虑数组[1, 3, 5, 6]tar = 5,在每个元素上使用上面的定义,我们可以看到数组实际上可以计算为[F, F, T, T],所以我们需要做的就是找到索引第一个T。这同样适用于任何数组。

实施

现在问题的核心来了。我将首先说明为什么组合 2 和 3 不起作用。

在组合 2 中, l=0, r=len-1 (inbound); loop(l &lt; r); l=ind+1, r=ind (include);:
我们可以看到r 被初始化为len - 1。但是,如果给定数组的计算结果为 [F, F, F, F] 怎么办?答案是4,但r 被初始化为3,这意味着4 永远不会被视为答案。

在组合 3 中,l=0, r=len (inbound); loop(l &lt; r); l=ind+1, r=ind-1 (exclude);:
如果ns[ind] &gt; tar,我们可以看到r=ind-1。但是,我们希望找到第一个i,这样ns[ind] &gt;= tar 所以ns[ind] 仍然是一个潜在的候选人!因此,在这个阶段排除它是不正确的。

要考虑的一个例子是[3, 4, 5]tar = 4。在第一次迭代中,ind = 14 立即被淘汰,这应该是正确的答案。

您可以通过查看您的二分搜索是否会错误地排除潜在候选人来验证其他组合是否正常工作。

补充说明

正如您所说,使用哪个索引组合确实取决于问题。但是,在这个特定问题中,如果要求我找到第一个 ins[i] &gt;= tar,我将有一个更简洁的实现,如下所示:

var searchInsert = function (ns, tar) {
  let l = 0;
  let r = ns.length;
  let ind;
  ns.push(Infinity);
  while (l < r) {
    ind = Math.floor((l + r) / 2);
    if (ns[ind] >= tar) {
      r = ind;
    } else {
      l = ind + 1;
    }
  }
  return r; // insert
};

这只是在数组中找到第一个T

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-16
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多