微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

找到一维的最短路径

如何解决找到一维的最短路径

| 在一维数组S中,可能有任意数量的元素属于该集合
U:{A,B,C,D,E}  
并允许重复。 范例:
S  = {E,A,E,C} 
问题是: 在任何给定数组S中,确定包含属于集合U的所有元素的最短范围/路径的最有效方法是什么?请记住,数组无法排序。 在上面的示例中,最短路径是连接数组S的前5个元素的路径。 编辑: 1)集U的元素数不是恒定的。 提前致谢。     

解决方法

有趣的作业,但是您仍然必须自己编写代码。 好消息是您没有告诉我们您使用哪种语言,因此当您决定自己编写代码时,我以它为标志,这很好。 到目前为止,我最好的尝试: 有2个用于子字符串(范围)的指针,一个用于范围的开始(较小的索引),而一个用于结束(较大的索引)的指针。两者都首先指向数组的开头。 分别列出范围内的ABCDE数量。 从左到右迭代结束。 对于每个字符,增加列表中该字符的编号。如果结果(增加了多少)> 1(请看起始点是否指向同一个字符。如果是,则向前移动起始字符并减去1,和),而起始指向与之相关的数字> 1的字符,向前移动起始字符和减1。 如果列表中的ABCDE全部> = 1,那么我们已经找到一个候选范围。将其与最短长度(如果有)进行比较,如果更短,则更新最短长度并记录新最短范围的开始索引。     ,如果我对问题的理解正确,我认为您需要做(语言不可知)
int partLen <- U.length;
do {
    Vector subSets <- S.partition(partLen);
    foreach set I in subSets
        if I.isEqualTo(U) then
            return true;
        else
            partLen <- partLen + 1;
} while (partLen <= S.length);
return false;
partition
会将S分解为任何长度的子集
isEqualTo
可以正确比较集合。     ,首先在数组中找到不同的元素,它们是O(n)的东西。然后使用滑动窗口方法找到所有这些元素都存在的最小跨度。 您可以在此处查看如何找到最小窗口:http://tech-queries.blogspot.com/2010/12/finding-minimum-window-in-array-which.html     ,这是一个简单的算法,它会扫描阵列一次,并不断检查其当前看到的覆盖范围是否比以前看到的覆盖范围短。 为简单起见,我假设我们可以将A,B,C,D和E映射到整数0-4,以便我们可以轻松地引用数组。我尚未对其进行彻底检查,因此请在思想上/实际上在一个或两个示例上运行它,以确保它能够满足您的要求。
//Cell 0 is the last index at which we saw an A,cell 1 \" \" saw a B,etc.
int[] mostRecent = new int[U.length];
mostRecent.setAllValsTo(POSITIVE_INFINITY);

int shortestRange = POSITIVE_INFINITY; //We are trying to minimize this number.
int minIndex = 0; //The beginning index of the range
int maxIndex = POSITIVE_INFINITY; //The ending index of the range.

for(int i=0; i< S.length; i++) {
    int currentValue = S[i]; //This value will be 0-4,corresponding to A-E

    mostRecent[currentValue] = i;

    currentMax = mostRecent.findMax(); //beginning of current range
    currentMin = mostRecent.findMin(); //end of current range
    currentRange = currentMax - currentMin;

    if(currentRange < shortestRange) {
        shortestRange = currentRage;
        minIndex = currentMin;
        maxIndex = currentMax;
    }
}

//currentMax and currentMin now carry the starting and ending indices,use them as you see fit.
return shortestRange;
这是O(nk)阶,其中n = S.length,k = U.length。仍然有很多优化方法可以解决,但我不知道我是否可以降低最坏情况的订单量。     ,这是我的方法(用伪代码)
let counters[] be an array such that 
counters[j] = number of occurrences of character j,where j = 0 for \'A\',j = 1 for \'B\',etc.

build counters[] by scanning the original string s

let positions[j][] be an array listing the positions occupied by 
character j in the original string s; note the size of 
positions[j][] is equal to counters[j]

build positions[j][] by scanning the original string s;

let currentPositions[] be an array such that 
positions[j][currentPositions[j]] gives the position of the next 
occurrence of character j in the original string s

initially currentPositions[j] = 0 for every j = [0 .. u.length]

let bestLength = s.length
let bestMin = 0
let bestMax = 0
for i in [0 .. s.length] {
    for j in [0 .. u.length] {
        if ( 
          positions[i][currentPositions[i]] < i and 
          currentPositions[j] + 1 < counters[j]
        )
          currentPositions[j]++
    }
    let min = s.length
    int max = 0
    for j in [0 .. u.length] {
        curPos = positions[j][currentPositions[j]
        if (curPos > max) let max = curPos
        if (curPos < min) let min = curPos
    }
    if (max - min + 1 < bestLength) {
        let bestMin = min
        let bestMax = max
        let bestLength = max - min + 1
    }
}

the shortest path is that starting at bestMin,ending at bestMax,and having length bestLength
复杂度为O(nk),其中n = s.length,k = u.length     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。