Algorithm 具有2个唯一数字的最大连续子阵列的长度

Algorithm 具有2个唯一数字的最大连续子阵列的长度,algorithm,vector,data-structures,Algorithm,Vector,Data Structures,我有一个数字数组,我想计算出由两个唯一数字组成的连续子数组的最大长度 例如,[2,3,4,3,2,2,4]将返回3,因为[3,2,2]的长度为3 [2, 4, 2, 5, 1, 5, 4, 2] would return 3. [7, 8, 7, 8, 7] would return 5. 编辑:我考虑过一个O(n^2)解决方案,从数组中的每个值开始,迭代直到看到第三个唯一值 for item in array: iterate until third unique element

我有一个数字数组,我想计算出由两个唯一数字组成的连续子数组的最大长度

例如,[2,3,4,3,2,2,4]将返回3,因为[3,2,2]的长度为3

[2, 4, 2, 5, 1, 5, 4, 2] would return 3.
[7, 8, 7, 8, 7] would return 5.
编辑:我考虑过一个O(n^2)解决方案,从数组中的每个值开始,迭代直到看到第三个唯一值

for item in array:
    iterate until third unique element
    if length of this iteration is greater than existing max, update the max length
return maxlength
然而,我不认为这是一个有效的解决方案。

这可以通过O(n)实现。代码是用python3编写的
o
t
分别为一和二
m
是最大值,
c
是当前计数变量

a = [7, 8, 7, 8, 7]
m = -1
o = a[0]
t = a[1]
# in the beginning one and two are the first 2 numbers 
c = 0
index = 0
for i in a:
    if i == o or i == t:
        # if current element is either one or two current count is increased
        c += 1
    else:
        # if current element is neither one nor two then they are updated accordingly and max is updated
        o = a[index - 1]
        t = a[index]
        m = max(m, c)
        c = 2
    index += 1
m = max(m, c)

print(m)

我们可以使用双指针技术在O(n)运行时复杂性中解决这个问题。这两个指针,例如
startPtr
endPtr
将表示数组中的范围。我们将保持此范围
[startPtr,endPtr]
,使其包含的唯一编号不超过2个。我们可以通过跟踪2个唯一数字的位置来实现这一点。我的C++实现如下:

int main()
{
    int array[] = {1,2,3,3,2,3,2,3,2,2,2,1,3,4};
    int startPtr = 0;
    int endPtr = 0;

    // denotes the size of the array
    int size= sizeof(array)/sizeof(array[0]);

    // contain last position of unique number 1 in the range [startPtr, endPtr] 
    int uniqueNumPos1 = -1; // -1 value represents it is not set yet

    // contain last position of unique number 2 in the range [startPtr, endPtr]
    int uniqueNumPos2 = -1; // -1 value represents it is not set yet


    // contains length of maximum continuous subarray with 2 unique numbers
    int ans = 0;

    while(endPtr < size) {
        if(uniqueNumPos1 == -1 || array[endPtr] == array[uniqueNumPos1]) {
            uniqueNumPos1 = endPtr;
        }
        else {
            if(uniqueNumPos2 == -1 || array[endPtr] == array[uniqueNumPos2]) {
                uniqueNumPos2 = endPtr;
            }
            else {
                // for this new third unique number update startPtr with min(uniqueNumPos1, uniqueNumPos2) + 1
                // to ensure [startPtr, endPtr] does not contain more that two unique
                startPtr = min(uniqueNumPos1, uniqueNumPos2) + 1;

                // update uniqueNumPos1 and uniqueNumPos2
                uniqueNumPos1 = endPtr -1;
                uniqueNumPos2 = endPtr;
            }
        }

        // this conditon is to ensure the range contain exactly two unique number
        // if you are looking for the range containing less than or equal to two unique number, then you can omit this condition
        if (uniqueNumPos1 != -1 && uniqueNumPos2 !=-1) {
            ans = max( ans, endPtr - startPtr + 1);
        }

        endPtr++;
    }

    printf("%d\n", ans);
}
intmain()
{
int数组[]={1,2,3,3,2,3,2,3,2,2,2,1,3,4};
int startPtr=0;
int-endPtr=0;
//表示数组的大小
int size=sizeof(数组)/sizeof(数组[0]);
//包含范围[startPtr,endPtr]中唯一编号1的最后位置
int uniqueNumPos1=-1;//-1值表示尚未设置
//包含范围[startPtr,endPtr]中唯一编号2的最后位置
int uniqueNumPos2=-1;/-1值表示尚未设置
//包含具有2个唯一数字的最大连续子阵列的长度
int ans=0;
while(endPtr
感谢MBo指出错误

import java.util.Arrays;
import static java.lang.System.out;
class TestCase{
    int[] test;
    int answer;
    TestCase(int[] test,int answer){
        this.test = test;
        this.answer = answer;
    }
}
public class Solution {
    public static void main(String[] args) {
        TestCase[] tests = {
                            new TestCase(new int[]{2, 3, 4, 3, 2, 2, 4},3),
                            new TestCase(new int[]{2, 3, 3, 3, 3, 4, 3, 3, 2, 2, 4},7),
                            new TestCase(new int[]{1,2,3,3,4,2,3,2,3,2,2,2,1,3,4},7),
                            new TestCase(new int[]{2, 7, 8, 7, 8, 7},5),          
                            new TestCase(new int[]{-1,2,2,2,2,2,2,2,2,2,2,-1,-1,4},13),
                            new TestCase(new int[]{1,2,3,4,5,6,7,7},3),
                            new TestCase(new int[]{0,0,0,0,0},0),
                            new TestCase(new int[]{0,0,0,2,2,2,1,1,1,1},7),
                            new TestCase(new int[]{},0)
        };

        for(int i=0;i<tests.length;++i){
            int ans = maxContiguousArrayWith2UniqueElements(tests[i].test);
            out.println(Arrays.toString(tests[i].test));
            out.println("Expected: " + tests[i].answer);
            out.println("Returned: " + ans);
            out.println("Result: " + (tests[i].answer == ans ? "ok" : "not ok"));
            out.println();
        }         
    }

    private static int maxContiguousArrayWith2UniqueElements(int[] A){
        if(A == null || A.length <= 1) return 0;
        int max_subarray = 0;
        int first_number = A[0],second_number = A[0];
        int start_index = 0,same_element_run_length = 1;
        for(int i=1;i<A.length;++i){
            if(A[i] != A[i-1]){ 
                if(first_number == second_number){
                    second_number = A[i];
                }else{
                    if(A[i] != first_number && A[i] != second_number){
                        max_subarray = Math.max(max_subarray,i - start_index); 
                        start_index = i - same_element_run_length;
                        first_number  = A[i-1];
                        second_number = A[i];
                    }
                }
                same_element_run_length = 1;
            }else{
                same_element_run_length++;
            }
        }

        return first_number == second_number ? max_subarray : Math.max(max_subarray,A.length - start_index);
    }
}
算法:

[2, 3, 4, 3, 2, 2, 4]
Expected: 3
Returned: 3
Result: ok

[2, 3, 3, 3, 3, 4, 3, 3, 2, 2, 4]
Expected: 7
Returned: 7
Result: ok

[1, 2, 3, 3, 4, 2, 3, 2, 3, 2, 2, 2, 1, 3, 4]
Expected: 7
Returned: 7
Result: ok

[2, 7, 8, 7, 8, 7]
Expected: 5
Returned: 5
Result: ok

[-1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, 4]
Expected: 13
Returned: 13
Result: ok

[1, 2, 3, 4, 5, 6, 7, 7]
Expected: 3
Returned: 3
Result: ok

[0, 0, 0, 0, 0]
Expected: 0
Returned: 0
Result: ok

[0, 0, 0, 2, 2, 2, 1, 1, 1, 1]
Expected: 7
Returned: 7
Result: ok

[]
Expected: 0
Returned: 0
Result: ok
  • 因此,我们维护两个变量第一个\u编号第二个\u编号,它们将保存这两个唯一的编号 正如你所知道的,为了得到最大的子数组长度,我们需要考虑很多子数组,它有2个唯一的元素。因此,我们需要一个指针变量,它将指向子数组的开始。在这种情况下,该指针是开始索引
  • 当我们发现第三个数字不等于第一个第二个时,任何子数组都会中断。因此,现在,我们通过执行i-start\u index来计算先前的子阵列长度(具有这两个唯一元素)
  • 这个问题的棘手部分是如何获得下一个子数组的开始索引
  • 如果您仔细观察,second\u number前一个子数组变为当前子数组的first\u number,而我们刚才遇到的third变为当前子数组的second\u number
  • 因此,计算此第一个\u编号何时开始的一种方法是向后运行一个while循环,以获得该开始\u索引。但是如果有很多子阵需要考虑的话,那么这将使得算法O(n^2)
  • 因此,我们维护一个名为same_element_run_length的变量,该变量只跟踪数字重复多少次的长度或频率,并在数字中断时进行更新。因此,start\u index在我们遇到第三个数字后,下一个子阵的开始索引变为start\u index=i-相同的元素运行长度
  • 剩下的计算是不言自明的
  • 时间复杂度:O(n),空间复杂度:O(1)

您尝试过什么?如果你发布一个部分解决方案,而不是要求其他人为你编写一个完整的解决方案,你更有可能得到一个有用的答案。
重复2个数字的最大长度是多少,直到我看到第三个唯一的数字,这意味着,在下面的示例中,你是如何得到5和3的,请澄清?我已经添加了我尝试过的方法。我得到了5,因为该数组中只有2个唯一的元素,所以我可以遍历整个数组(大小为5)。我想找出2个唯一元素的最大子数组的长度。我在前面的数组中得到了3,因为[2,4,2]或[5,1,5]都是长度为3的。我刚刚重命名了这个问题,以便更恰当地反映手上的问题。在第一个示例中,3,4,3不是返回3吗?a.index()的复杂度是多少?它是O(n),我的错。但是,由于我使用的是当前元素的索引,而不是在整个数组中搜索,因此不需要使用,并且可以使用O(1)中的索引变量来使用。请根据编辑答案尝试使用
a=[2,7,8,7,8,7]
。解决方案错误。已修复,需要在退出循环后更新m,感谢反馈
i