查找堆栈中最长的字符序列

Posted

技术标签:

【中文标题】查找堆栈中最长的字符序列【英文标题】:Find longest sequence of characters in stack 【发布时间】:2016-09-13 19:58:27 【问题描述】:

您好,我正在解决一个问题:

给定一个以 10 为底的整数 n,将其转换为二进制(以 2 为底)。然后找到并 打印以 10 为底的整数,表示连续 1 的最大数量 在 n 的二进制表示中。例如对于 n=5,base-2 = 101 所以输出应该是 1,对于 n = 439,base-2 = 110110111 所以输出应该是 3。

下面是我的代码解决方案:

class Solution 

    static int CalcBinary (int n) 
        Stack<int> binRep = new Stack<int>();
        while (n > 0) 
            int i = n%2;
            binRep.Push (i);
            n = n/2;
        
        int oldCount = 0, newCount = 0;
        while (binRep.Count > 0)
            int val = binRep.Pop();
            if (val == 1) 
                newCount++;
             else 
                if (newCount > oldCount) 
                    oldCount = newCount;
                
                newCount = 0;
            
        
        return (newCount > oldCount) ? newCount : oldCount;
    

    static void Main(String[] args) 
        int n = Convert.ToInt32(Console.ReadLine());
        Console.WriteLine (CalcBinary(n));
    

代码运行良好,并通过了所有测试用例,例如 n = 5、6、439 等。我唯一的问题是,是否有任何优化的解决方案可以做到这一点。其他人发布了相同的问题here,但对该问题的所有回复似乎都与 O(n) 时间复杂度相同。另一件事是我可以使用数组而不是堆栈,但这有什么不同吗??

【问题讨论】:

437 (110110101) 的答案是什么? 2? 我认为计算一个数字中的 1 位(即 O(1 的数量))可能适用于这种情况,以获得比固定长度数字的 O(位数)更好... (只是猜测,不完全确定会不会成功) 我很确定您的意思是 O(log n),除非 n 是二进制位数而不是数字本身。 有什么理由需要使用堆栈或数组 - 您可以直接处理整数值吗? while (n > 0) if ((n%2) == 1) ....... @UweKeim,在此之前我遇到过问题,虽然我的问题在 *** 上有效,但在代码审查中却是负面的。所以我更愿意在这里问他们。 【参考方案1】:
public int CalcBinary(int n)

    int result = 0;
    int current = 0;
    for (int i = 0; i + result < 32 && (n >> i) != 0; i++)
    
        if (((n >> i) & 1) == 1)
            current += 1;
        else
        
            if (current > result) 
                result = current;
            current = 0;
        
    

    return result == 0 ? current : result;

我不太擅长大 O 算术,但我认为这个解决方案应该更快,因为我不使用任何其他类,只使用简单的位移。

如果不再有解决方案,我提早停止 (i + result &lt; 32)。

注意,这仅适用于 32 位 整数。对于 64 位,请调整上述条件。它仅适用于 值(设置符号位会产生错误的结果,例如 111....111101)。


更新:按照@Scott-Chamberlain 的建议添加了(n &gt;&gt; i) != 0 条件(它检查是否还有1s 会出现)。

【讨论】:

你也可以通过i + result &lt; 32 &amp;&amp; n &gt;&gt; i != 0提前退出 @ScottChamberlain 我不明白,不应该是i + result &lt; 32 || (n &gt;&gt; i) == 0 吗?所以 int 的“上其余部分”是零? @ScottChamberlain 啊抱歉,我的错,for 循环的条件继续...我在脑海中将其转为退出条件【参考方案2】:

为什么在转换二进制时不计算maximum_consecutive而不是等待转换完成,然后从堆栈中再次计算maximum_consecutive

我认为你应该改变这个。

class Solution 

static int CalcBinary (int n) 
    int oldCount = 0, newCount = 0;
    while (n > 0) 
        int i = n%2;
        n = n/2;

        if (i == 1) 
            newCount++;
        
        else 
            if (newCount > oldCount) 
                oldCount = newCount;
            
            newCount = 0;
        

    
    return (newCount > oldCount) ? newCount : oldCount;


static void Main(String[] args) 
    int n = Convert.ToInt32(Console.ReadLine());
    Console.WriteLine (CalcBinary(n));


【讨论】:

是的,实际上这使我免于创建堆栈。谢谢。【参考方案3】:

为了有趣和最小的分支:

int[] lookup = new[]

  0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 
  31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
;
int LongestRunOfBits(uint value)

    int max = 0;
    while(1 << max < value + 1)
    
        uint testValue = ~value;
        uint lookupIndex = ((uint)((testValue & -testValue) * 0x077CB531U)) >> 27;
        int trailingZeros = lookup[lookupIndex];
        max = trailingZeros - ((trailingZeros - max) & ((trailingZeros - max) >> 31));
        value >>= 1;
    
    return max;

这结合了以下操作:

Compute the maximum of two integers without branching(QuAD 版本)

Count the consecutive zero bits (trailing) on the right with multiply and lookup(如果它计算value 上的尾随零位,那么它计算~value 上的尾随一位)

让我们来看看value 6 或110

现在我们有了:

值:000000000000000000000000000000110 〜价值:1111111111111111111111111111001 尾随零位:0 rsh 后的值:000000000000000000000000000000011 〜价值:1111111111111111111111111111100 尾随零位:2 rsh 之后的值:00000000000000000000000000000001 //跳过最后一次迭代 ~value : 11111111111111111111111111111110 //因为现在不可能 尾随零位:1 //找到一个> 2的值

通过找到~value 的最大尾随零位数,我们有效地找到了value 的最大尾随一位数。如果我们继续右移直到没有剩余的位,最长的设置位运行是我们在~value 上执行的尾随零位操作的最大值。万岁。一旦我们找到值 2 并且该值中剩余的位数为 2 或更少,我们可以提前放弃,因为我们可以确定找不到大于 2 的值,因此可以跳过最后一次迭代。

【讨论】:

以上是关于查找堆栈中最长的字符序列的主要内容,如果未能解决你的问题,请参考以下文章

数组篇在python中如何查找最长字符串子串

每日一题查找两个字符串中的最长公共子串

每日一题查找两个字符串中的最长公共子串

[LCS] nwHJ65 查找两个字符串a,b中的最长公共子串(LCS+KMP+substr暴力)

[LCS] nwHJ65 查找两个字符串a,b中的最长公共子串(LCS+KMP+substr暴力)

[LCS] nwHJ65 查找两个字符串a,b中的最长公共子串(LCS+KMP+substr暴力)