编号中的数字花盆

时间:2015-05-21 19:47:29

标签: algorithm dynamic-programming

这是一个Google面试问题。只有“T”和“F”的列表。 All表示一个位置,使得T意味着位置被花盆占据而F意味着锅不在那里,所以你可以在这个位置放另一个锅。找出可以放置在给定布置中的盆的数量,使得没有两个盆彼此相邻(它们在给定的布置中可以相邻)。如果开头的位置未被占用,那么如果第二个位置也未被占用,并且如果最后一个位置未被占用而且如果第二个最后位置也未被占用则可以放置一个底池,则可以放置一个底池。对于前。

TFFFTFFTFFFFT - 返回2 FFTTFFFFFTTFF - 返回4

我尝试通过查看具有值F的每个位置的相邻值来解决它。如果两个相邻位置都是F并且将此位置设置为T,则增加计数器。我需要更好的解决方案或任何其他解决方案(如果有的话)。 / p>

6 个答案:

答案 0 :(得分:0)

我会像这样处理问题。你需要FFF再增加一个底池,两个底池有FFFFF等。要处理最终情况,请在每一端添加一个F.

因为这与16位整数非常相似,所以算法应该使用像二进制算术运算这样的技巧。

这是Python中的一个实现,它使用位掩码(value & 1),位移(value >>= 1)和数学((zeros - 1) / 2)来计算空槽并计算可以有多少个花盆配合。

#value = 0b1000100100001
value = 0b0011000001100
width = 13
print bin(value)

pots = 0        # number of flower pots possible
zeros = 1       # number of zero bits in a row, start with one leading zero
for i in range(width):
    if value & 1:       # bit is one, count the number of zeros
        if zeros > 0:
            pots += (zeros - 1) / 2 
        zeros = 0
    else:       # bit is zero, increment the number found
        zeros += 1
    value >>= 1         # shift the bits to the right
zeros += 1              # add one trailing zero
pots += (zeros - 1) / 2 
print pots, "flower pots"

答案 1 :(得分:0)

您可以使用修改后的Mergesort执行此操作。考虑可以放置在单体中的花盆,然后可以放置在这些单体的双重合并中的花盆,在树上到完整的排列。它将在O(n lg n)中填写n个花盆列表。

使用复杂O(n^2)的修改棒切割算法肯定有办法做到这一点。子问题是一个开放的假设置"存在于正在考虑的子字符串中。 "关闭错误集"已经为它们计算了一些最大值。因此,当添加一个新角色时,它会增加可以插入的花盆数量,或者锁定在"子串的最大可用花盆数量。

另外,您知道可以放置在由关闭位置约束的一组 n 开仓位置的最大花盆是 n - 2 (否则 n -1 如果只在一侧括起来,即字符串以" false set"开始或结束。基本条件(第一个位置打开,或第一个位置关闭)可以计算到达第二个花盆。

因此,我们可以根据可以插入较小的子排列的花盆的最大数量来建立可以插入整个排列的花盆总数之前已经计算过的。通过将我们先前的计算存储在一个数组中,我们将计算下一个子排列的最大值所需的时间减少到单个数组查找和一些恒定时间计算。这是动态编程的精髓!

编辑:我更新了答案以提供动态编程方法的说明。请考虑使用我在评论中提到的互动教科书! http://interactivepython.org/runestone/static/pythonds/index.html

答案 2 :(得分:0)

让我们分析一下必须做些什么。

首先,我们可能需要访问并检查每个地方。这表明某种循环。 E.g:

for (int i = 0; i < myPlaces.Length; ++i)

当我们在某个地点时,我们必须检查它是否被占用

if (place[i] == 'F')

但这还不足以将花盆放在那里。我们必须检查下一个和上一个地方是否免费

place[i-1]
place[i+1]

如果所有树都包含F,您可以将花盆放在那里并移动到下一个字段

现在,我们也有一些例外情况。列表的开头和结尾。所以你必须单独处理它们。 E.g

if (i == 0)
{
    // only check current position and next position
}

if (i == myPlaces.Length - 1) // minus 1 because indexing usually starts from 0
{
    // only check current position and previous position
}

之后,您可以执行前面提到的检查。

现在让我们考虑一下输入数据。通常,不习惯修改输入数据,而是复制并处理副本是一个好习惯。对于不同的任务,一些数据结构也比其他数据结构更好。在这里,您可以使用简单的字符串来保持条目值。但我会说一系列字符会是更好的选择,因为当你找到一个可以放花盆的地方时,你实际上可以用数组中的F替换T。然后,当您移动到新位置时,您的数据结构器知道前一个位置已经有一个底池,因此您的算法不会放置相邻的算法。 你不可能用字符串做,因为字符串是不可变的,你需要每次都生成一个新的字符串。

请注意,它只是一个天真的算法,有很多改进和优化的空间。但我的目标是更好地了解如何解决这类问题。在针对谷歌的工作之前,我将把这些细节的实施作为下午的练习。

答案 3 :(得分:0)

解决方案非常简单,检查位置的先前值和当前值,并将位置标记为可种植(或可放置)并递增计数。读取下一个值,如果它已经被种植,(回溯并且)改变先前的值并减少计数。复杂度为O(n)。我们真正想要检查的是1001的出现。以下是用Java实现的算法。

public boolean canPlaceFlowers(List<Boolean> flowerbed, int numberToPlace) {

    Boolean previous = false;
    boolean puttable = false;
    boolean prevChanged = false;
    int planted = 0;
    for (Boolean current : flowerbed) {
        if (previous == false && current == false) {
            puttable = true;
        }

        if (prevChanged == true && current == true) {
            planted--;
        }

        if (puttable) {
            previous = true;
            prevChanged = true;
            planted++;
            puttable = false;
        } else {
            previous = current;
            prevChanged = false;
        }
    }

    if (planted >= numberToPlace) {
        return true;
    }

    return false;
}

private static void canPlaceOneFlower(List<Boolean> flowerbed, FlowerBed fb) {
    boolean result;
    result = fb.canPlaceFlowers(flowerbed, 1);
    System.out.println("Can place 1 flower");
    if (result) {
        System.out.println("-->Yes");
    } else {
        System.out.println("-->No");
    }
}

private static void canPlaceTwoFlowers(List<Boolean> flowerbed, FlowerBed fb) {
    boolean result;
    result = fb.canPlaceFlowers(flowerbed, 2);
    System.out.println("Can place 2 flowers");
    if (result) {
        System.out.println("-->Yes");
    } else {
        System.out.println("-->No");
    }
}

private static void canPlaceThreeFlowers(List<Boolean> flowerbed, FlowerBed fb) {
    boolean result;
    result = fb.canPlaceFlowers(flowerbed, 3);
    System.out.println("Can place 3 flowers");
    if (result) {
        System.out.println("-->Yes");
    } else {
        System.out.println("-->No");
    }
}

private static void canPlaceFourFlowers(List<Boolean> flowerbed, FlowerBed fb) {
    boolean result;
    result = fb.canPlaceFlowers(flowerbed, 4);
    System.out.println("Can place 4 flowers");
    if (result) {
        System.out.println("-->Yes");
    } else {
        System.out.println("-->No");
    }
}


public static void main(String[] args) {
    List<Boolean> flowerbed = makeBed(new int[] { 0, 0, 0, 0, 0, 0, 0 });
    FlowerBed fb = new FlowerBed();

    canPlaceFourFlowers(flowerbed, fb);
    canPlaceThreeFlowers(flowerbed, fb);
    flowerbed = makeBed(new int[] { 0, 0, 0, 1, 0, 0, 0 });
    canPlaceFourFlowers(flowerbed, fb);
    canPlaceThreeFlowers(flowerbed, fb);
    canPlaceTwoFlowers(flowerbed, fb);

    flowerbed = makeBed(new int[] { 1, 0, 0, 1, 0, 0, 0, 1 });

    canPlaceFourFlowers(flowerbed, fb);
    canPlaceThreeFlowers(flowerbed, fb);
    canPlaceTwoFlowers(flowerbed, fb);
    canPlaceOneFlower(flowerbed, fb);

}

答案 4 :(得分:0)

我使用动态编程的解决方案。

ar的格式为[&#39; F&#39;,&#39; T&#39;&#39; F&#39;]。

import numpy as np
def pot(ar):
    s = len(ar)
    rt = np.zeros((s,s))
    for k in range(0,s):
        for i in range(s-k):
            for j in range(i,i+k+1):
                left = 0
                right = 0
                if ar[j] != 'F':
                    continue
                if j-1 >= i and ar[j-1] == 'T':
                    continue
                else:
                    left = 0
                if j+1 <= i+k and ar[j+1] == 'T':
                    continue
                else:
                    right = 0
                if j-2 >= i:
                    left = rt[i][j-2]
                if j+2 <= i+k:
                    right = rt[j+2][i+k]
                rt[i][i+k] = max(rt[i][i+k], left+right+1)
    return rt[0][len(ar)-1]

答案 5 :(得分:0)

我用C#编写的解决方案

    private static int CheckAvailableSlots(string str)
    {
        int counter = 0;
        char[] chrs = str.ToCharArray();

        if (chrs.FirstOrDefault().Equals('F'))
            if (chrs.Length == 1)
                counter++;
            else if (chrs.Skip(1).FirstOrDefault().Equals('F'))
                counter++;

        if (chrs.LastOrDefault().Equals('F') && chrs.Reverse().Skip(1).FirstOrDefault().Equals('F'))
            counter++;

        for (int i = 1; i < chrs.Length - 2; i++)
        {
            if (chrs[i - 1].Equals('T'))
                continue;
            else if (chrs[i].Equals('F') && chrs[i + 1].Equals('F'))
            {
                chrs[i] = 'T';
                counter++;
                i++;
            }
            else
                i++;
        }
        return counter;
    }