与最近邻居的最大差异

时间:2015-02-01 13:19:33

标签: python algorithm

我正在编写座位分配计划,并将问题集中在一排座位上。我想分配下一个座位,使其距离最近的座位最远。我认为问题可以写成如下:

给定一个(所有席位的)整数列表和一个子集(占用席位),找到与最近的相邻数字有最大差异的最小整数。

例如:

Input: [1,2,3,4,5,6,7,8,9,10], [1,10]
Output: 5
(Actually it is 5 or 6 but we take the smallest)
Input: [1,2,3,4,5,6,7,8,9,10], [5,10]
Output: 1
(1 is 4 numbers away from 5, any other number is 3 or less numbers away from 5 or 10)
Input: [1,2,3,4,5,6,7,8,9,10], [1,5,10]
Output: 3
(Possible candidates are 3, 7 or 8 but we take the smallest)

我试图通过所采用的子集循环每个剩余的整数并取平均值和差值之和但输出不正确。

我相信已经存在针对此问题的算法。你会使用哪种算法(以便我自己设定正确的方向)?谢谢。

4 个答案:

答案 0 :(得分:1)

假设我们有从1到n的席位。请注意,答案是1,n或最大未采用子序列的中心。检查1和n的最近邻居是直截了当的,所以让我们专注于寻找未采用的子序列。在这种情况下,我认为代码会说自己最好:

largest_free = 0, largest_begin
current_free = 0, current_begin = 0
for i = 1 to n:
    if i is taken:
        if current_free > largest_free:
            largest_free = current_free
            largest_begin = current_begin
        current_begin = i + 1
        current_free = 0
    else:
        current_free += 1

if current_free > largest_free:
    largest_free = current_free
    largest_begin = current_begin

整体算法显然需要一个线性时间。

答案 1 :(得分:1)

以下代码是关于可读性的,而不是关于性能的代码:

def find_max_dist(n, taken):
    # trivial cases: no or one seat taken
    if not taken:
        return 1
    elif len(taken) == 1:
        return 1 if list(taken)[0] > n//2 else n
    else: # interesting case
        taken = sorted(list(taken))
        gap_sizes = list(map(lambda x,y: y-x-1, taken, taken[1:]))
        biggest_gap_size = max(gap_sizes)

        # check if outermost seats are optimal
        if taken[0] > biggest_gap_size:
            return 1
        elif n - taken[-1] > biggest_gap_size:
            return n

        begin_of_biggest_gap = taken[gap_sizes.index(biggest_gap_size)] + 1
        return begin_of_biggest_gap + ((biggest_gap_size - 1)// 2)



print(find_max_dist(10, {}))

print(find_max_dist(10, {5}))
print(find_max_dist(10, {6}))

print(find_max_dist(11, {5}))
print(find_max_dist(11, {6}))

print(find_max_dist(10, {1, 10}))
print(find_max_dist(10, {5, 10}))
print(find_max_dist(10, {1, 5, 10}))

我认为taken是一个集合。如果此组合为空或仅包含一个元素,则选择是明确的:第一个座位如果为空,或者座位位于后半部分,否则为最后一个座位。

如果有多个座位,则确定最大差距。然后代码确定间隙中的第一个,最后一个或中间座位是最佳的。

对于您的上一个测试用例, 7 应该是答案,因为第二个差距更大。

答案 2 :(得分:0)

这对我来说似乎相当理想和可读:

try:
    from itertools import izip
except ImportError:  # Python 3
    izip = zip
from operator import itemgetter

def pairwise(iterable):
    "s -> (s0, s1), (s1, s2), (s2, s3), ..."
    return izip(*[iter(iterable)]*2)

def find_max_dist(all_seats, taken_seats):
    if len(taken_seats) == len(all_seats):  # no empty seats?
        return None

    # adds a virtual seat 0 if left-most taken seat isn't 1
    taken_seats = sorted(taken_seats + ([0] if taken_seats[0] != 1 else []))
    gaps = ((p0+1, p1-1, (p1-1)-(p0+1)) for p0, p1 in pairwise(taken_seats))
    max_gap = max(gaps, key=itemgetter(2))  # interval with largest gap

    # if left-most seat of largest gap is seat 1, use it, else use gap midpoint
    return 1 if max_gap[0] == 1 else (max_gap[0] + max_gap[1]) // 2

seats = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

print(find_max_dist(seats, [1, 10]))    # --> 5
print(find_max_dist(seats, [5, 10]))    # --> 1
print(find_max_dist(seats, [1, 5, 10])) # --> 3

答案 3 :(得分:0)

感谢您的所有答案和反馈。考虑到所有因素后,这是我的最终解决方案。

def findnextseat(n,taken):
    longestgapstart = 0
    longestgaplength = 0
    gapstart = 0
    gaplength = 0
    for i in range(1,n+1):
        if len(taken) == 0:
            longestgapstart = 1
            longestgaplength = n

        if i in taken:
            if gaplength > longestgaplength:
                longestgaplength = gaplength
                longestgapstart = gapstart 
            gaplength = 0
        else:
            if i == n:
                if gaplength > longestgaplength:
                    longestgaplength = gaplength
                    longestgapstart = gapstart 
            else:
                if gaplength == 0:
                    gapstart = i
                gaplength += 1

    if longestgapstart == 1:
        return 1
    elif longestgapstart + longestgaplength == n and n not in taken:
        return n
    else:
        return longestgapstart + (longestgaplength-1)/2

print findnextseat(10,[1,10])    #5
print findnextseat(10,[5,10])    #1
print findnextseat(10,[1,5,10])  #7
print findnextseat(10,[1,3])     #10
print findnextseat(10,[1,2,4,5,6,7,8,9]) #3

对于算法, dubov94 Jasper 用于指向测试用例的正确解决方案。