【问题标题】:Design a specific algorithm for a nxn array implemented on O(nlogn)为在 O(nlogn) 上实现的 nxn 数组设计特定算法
【发布时间】:2020-05-16 12:20:16
【问题描述】:

问题: 假设一个 n×n 数组 A 的每一行都由 1 和 0 组成,这样,在 A 的任何一行中,所有 1 都在该行中的任何 0 之前。假设 A 已经在内存中,描述一个在 O(nlogn) 时间(不是 O(n2) 时间!)内运行的方法来计算 A 中 1 的数量。

我的经验:我已经为 O(n) 做到了,但我不知道如何用 O(nlogN) 实现它 我将不胜感激!

【问题讨论】:

  • 你是如何在 O(n) 中完成的? (或者你的意思是 O(n²)?)
  • 这不是一个帖子,您可以在自己破坏后删除您的问题。
  • 你不应该一得到答案就删除你的问题!
  • Stack Overflow 几乎从不只针对提出问题的人。它也将成为未来每个人有用的问题和答案的存储库。请不要提问,然后用垃圾替换文本并删除问题。

标签: c arrays algorithm


【解决方案1】:

考虑每个单独的行都包含所有1s,后跟所有0s:

1111111000

您可以使用二进制搜索来查找转换点(行中的最后一个1)。其工作方式是在两端设置低和高并检查中间。

如果您处于过渡点,那么您就完成了。否则,如果您在1s 中,则在中点之后设置为低1。否则,您在0s 中,所以在中点之前设置高1。

类似于(伪代码,经过一些优化):

def countOnes(row):
    # Special cases first, , empty, all 0s, or all 1s.

    if row.length == 0: return 0
    if row[0] == "0": return 0
    if row[row.length - 1] == 1: return row.length

    # At this point, there must be at least one of each value,
    # so length >= 2. That means you're guaranteed to find a
    # transition point.

    lo = 0
    hi = row.length - 1
    while true:
        mid = (lo + hi) / 2
        if row[mid] == 1 and row[mid+1] == 0:
            return mid + 1
        if row[mid] == 1:
            lo = mid + 1
        else:
            hi = mid - 1

由于对单行的二进制搜索是O(logN),而您需要对N 行执行此操作,因此结果算法是O(NlogN)


更多具体示例,请参见以下完整的 Python 程序,该程序生成一个大部分随机矩阵,然后使用O(N) 方法和O(logN) 方法(前者作为确认)进行计数每行中的那些:

import random

def slow_count(items):
    count = 0
    for item in items:
        if item == 0:
            break
        count += 1
    return count

def fast_count(items):
    # Special cases first, no 1s or all 1s.

    if len(items) == 0: return 0
    if items[0] == 0: return 0
    if items[len(items) - 1] == 1: return len(items)

    # At this point, there must be at least one of each value,
    # so length >= 2. That means you're guaranteed to find a
    # transition point.

    lo = 0
    hi = len(items) - 1
    while True:
        mid = (lo + hi) // 2
        if items[mid] == 1 and items[mid+1] == 0:
            return mid + 1
        if items[mid] == 1:
            lo = mid + 1
        else:
            hi = mid - 1

# Ensure test data has rows with all zeros and all ones.

N = 20
matrix = [[1] * N, [0] * N]

# Populate other rows randomly.

random.seed()
for _ in range(N - 2):
    numOnes = random.randint(0, N)
    matrix.append([1] * numOnes + [0] * (N - numOnes))

# Print rows and counts using slow-proven and fast method.

for row in matrix:
    print(row, slow_count(row), fast_count(row))

fast_count 函数相当于我在此答案中提供的函数。

一个示例运行是:

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 20 20
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 0 0
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 5 5
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0] 15 15
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 10 10
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 1 1
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 11 11
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0] 12 12
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 11 11
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 1 1
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 6 6
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0] 16 16
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0] 14 14
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 11 11
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 9 9
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0] 13 13
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 1 1
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 4 4
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 6 6
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0] 19 19

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 2021-05-25
    相关资源
    最近更新 更多