Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 查找包含多达0次O(n)的1的最长子序列_Algorithm_Sorting_Count_Sequence - Fatal编程技术网

Algorithm 查找包含多达0次O(n)的1的最长子序列

Algorithm 查找包含多达0次O(n)的1的最长子序列,algorithm,sorting,count,sequence,Algorithm,Sorting,Count,Sequence,我在一次面试中遇到了一个问题,我找不到最佳解决方案(这真是令人沮丧,哈哈) 所以你有一个1和0的n列表。 110000110101110.. 目标是提取包含1到0的最长子序列。 例如,这里是“110000110101”或“10000101011”或“000011101110” 我对O(n^2)有一个想法,只是从头到尾扫描所有的可能性,但显然有一种方法可以在O(n)中实现。 有什么想法吗 非常感谢 考虑一下'10110': 创建一个变量S。创建数组A=[0] 从第一个数字开始迭代,如果注意到1,则

我在一次面试中遇到了一个问题,我找不到最佳解决方案(这真是令人沮丧,哈哈)

所以你有一个1和0的n列表。 110000110101110.. 目标是提取包含1到0的最长子序列。 例如,这里是“110000110101”或“10000101011”或“000011101110”

我对O(n^2)有一个想法,只是从头到尾扫描所有的可能性,但显然有一种方法可以在O(n)中实现。 有什么想法吗


非常感谢

考虑一下
'10110'

  • 创建一个变量
    S
    。创建数组
    A=[0]
  • 从第一个数字开始迭代,如果注意到1,则将1添加到S;如果注意到0,则从S中减去1,并将
    S
    附加到
    A

    • 对于我们的示例序列,
      A
      将是:
      [0,1,0,1,2,1]
      A
      只是一个数组,它存储索引前面的1和0之间的差值。序列必须在1s和0s之间具有相同差异的位置开始和结束。所以现在我们的任务是在
      A
      中找到相同数字之间的最长距离
  • 现在创建两个空字典(哈希映射)
    First
    Last

  • 迭代
    A
    并将
    A
    中每个数字的第一次出现位置保存在字典
    first

  • 迭代
    A
    (从末尾开始),并在字典
    last
    中保存每个数字在
    A
    中最后一次出现的位置

    • 因此,对于我们的示例,首先是
      {0:0,1:1,2:4}
      ,最后是
      {0:2,1:5,2:4}
  • 现在查找
    max_key
    )键,该键的
    First
    Last
    中的对应值之间的差值最大。此最大差异是子序列的长度。子序列从
    第一个[max\u key]
    开始,到
    最后一个[max\u key]
    结束

  • 我知道这有点难理解,但它有复杂度O(n)-四个循环,每个循环有复杂度n。当然,你可以用数组替换字典,但它比使用字典更复杂

    Python中的解决方案

    def find_子序列(seq):
    S=0
    A=[0]
    对于下文中的e:
    如果e=='1':
    S+=1
    其他:
    S-=1
    A.追加(S)
    第一={}
    最后={}
    对于位置,枚举(A)中的e:
    如果e不在第一位:
    第一[e]=pos
    对于位置,枚举中的e(反向(A)):
    如果e不在最后:
    最后[e]=长度(顺序)-位置
    最大差值=0
    最大密钥=无
    对于“先输入”选项:
    差异=最后一个[键]-第一个[键]
    如果差异>最大差异:
    最大差值=差值
    最大键=键
    如果max_key为None:
    返回“”
    返回顺序[第一个[最大键]:最后一个[最大键]]
    查找顺序('10110')#给出'0110'
    查找序列('1')#给出“”
    
    它更加优化


    额外的

    这一问题与环境有关。其解决方案也基于从一开始就对元素求和:

    def max_subarray(arr):
        max_diff = total = min_total = start = tstart = end = 0
        for pos, val in enumerate(arr, 1):
            total += val
            if min_total > total:
                min_total = total
                tstart =  pos
            if total - min_total > max_diff:
                max_diff = total - min_total
                end = pos
                start = tstart
        return max_diff, arr[start:end]
    

    你是说最长的子串(即元素必须是连续的(相邻的))吗?通常,子序列允许间隙,例如,
    [1,3]
    [1,2,3]
    的子序列。子序列将是微不足道的。只需把整个序列去掉多余的0/1。@PiotrDabkowski:是的。这就是我问的原因(因为我认为OP的意思是
    子字符串
    )。@J.F.Sebastian您的代码要好得多。我尽量让事情简单易懂:)顺便问一下,你写这段代码花了多长时间?
    git log
    表示从最初提交(答案中的代码)到最终版本之间的时间超过了一个小时。我试着想出一种类似于单次通过、恒定内存算法的方法,但失败了。@J.F.Sebastian您成功地实现了单次通过。我认为不可能让它成为永久的记忆。在Kadane的算法中,您正在寻找值之间的最大差异。这里你要寻找的是相同值之间的最大距离。