所有城市旅行所需的最短天数

时间:2017-10-29 13:49:10

标签: python algorithm data-structures

这是我在编码挑战中遇到的一个有趣的问题:

有k个城市和n天。旅行社将在第n天向您展示城市k。您应该找到可以访问所有城市的最少天数。您也被允许不止一次访问城市,但理想情况下,您不希望这样做,因为您希望最大限度地减少天数。

输入:您获得了一系列日期和城市,其中天数是指数,城市是值。 A = [7,4,7,3,4,1,7]所以A [0] = 7意味着旅行社会在第0天显示城市7,在第1天显示城市4等。

所以,如果您从第0天开始,您将在第5天访问所有城市,但您也可以在第2天开始并在第5天结束。

输出:4因为至少花了4天时间访问所有城市

我的解决方案:我确实有一个O(N ^ 2)解决方案,可以尝试所有城市组合。但是测试说理想的时间和空间复杂度应该是O(N)。我该怎么做?

def findmin(A):
    hashtable1={}
    locationcount=0
    #get the number of unique locations
    for x in A:
        if A[x] not in hashtable1:
            locationcount+=1

    index1=0
    daycount=sys.maxint
    hashtable2={}
    #brute force
    while index1<len(A):
        index2=index1
        prevday=index2
        ans=0
        count1=0
        while index2<len(A):
            if A[index2] not in hashtable2:
                count1+=1
                ans+=(index2-prevday)
                hashtable2[A[index2]]=1
            index2+=1
        if count1==count:
            daycount=min(ans,daycount)
        hashtable2.clear()
        index1+=1
    return daycount+1

3 个答案:

答案 0 :(得分:2)

这个问题可以通过双指针方法解决。

某些数据结构应包含当前窗口中的元素计数。也许你的哈希表是合适的。

将左右指针设置为列表的开头。

移动右指针,为这样的元素递增表条目:

  hashtable2[A[rightindex]] = hashtable2[A[rightindex]] + 1

当所有(locationcount)表条目变为非零时,停止向右移动指针。你有左右间隔覆盖所有城市。记住间隔长度。

现在移动左指针,递减表条目。当某些表条目变为零时,停止移动左指针。

再次移动右指针。重复直到列表结束。

请注意,索引只运行一次列表,复杂性是线性的(如果表条目更新为O(1),则哈希映射平均提供)

答案 1 :(得分:0)

我在面试中遇到了这个问题并且失败了,因为我想到移动窗户太晚了。几天后我拿了它,这是我的 C# 解决方案,我认为它是 O(n)(数组最多会被解析 2 次)。

我刷完之后剩下的难点是理解如何更新结束指针。可能有更好的解决方案,即使假期可以提前开始,我的解决方案也将始终提供尽可能高的开始和结束天数。

    public int solution(int[] A) {

        if (A.Length is 0 or 1) {
            return A.Length;
        }

        var startingIndex = 0;
        var endingIndex = 0;
        var locationVisitedCounter = new int[A.Length];
        locationVisitedCounter[A[0] - 1] = 1;

        for (var i=1; i<A.Length; i++)
        {
            var locationIndex = A[i] - 1;

            locationVisitedCounter[locationIndex]++;

            if (A[i] == A[i - 1])
            {
                continue;
            }

            endingIndex=i;

            while (locationVisitedCounter[A[startingIndex] - 1] > 1)
            {
                locationVisitedCounter[A[startingIndex] - 1]--;
                startingIndex++;
            }

        }

        return endingIndex - startingIndex + 1;
    }

答案 2 :(得分:0)

Python 解决方案

`定义假期(A):

# Get all unique vacation locations
v_set = set(A)
a_l = len(A)

day_count = 0

# Maximum days to cover all locations will be the length of the array
max_day_count = a_l 

for i in range(a_l):
    count = 0
    v_set_copy = v_set.copy()
    
    # Starting point to find next number of days 
    #that covers all unique locations

    for j in range(i, a_l):
        
        # Remove from set, if the location exists, 
        # meaning we have visited the location

        if (A[j] in v_set_copy):
            v_set_copy.remove(A[j])
        else:
            pass
        count = count + 1
        
        # If we have visited all locations, 
        # determine the current minimum days needed to visit all and break

        if (len(v_set_copy) == 0):
            day_count = min(count, max_day_count)
            max_day_count = day_count
            break
        
return day_count`