如何改进Max Common Array Slice的算法?

时间:2016-07-26 12:32:18

标签: java arrays algorithm

我被要求进行HackerRank代码测试,我被问到的练习是Max Common Array Slice。问题如下:

  

给定n个整数的序列a0,a1,.... 。 。 ,an-1和   任务是找到不再包含的数组的最大切片   比两个不同的数字。

     

输入1:

     

[1,1,1,2,2,2,1,1,2,2,6,2,1,8]

     

结果1:答案是10,因为(0,9)的数组切片是   数组的最大切片,不超过两个不同的数字。

     
      
  • 此片段中有10个项目是" 1,1,2,2,2,1,1,2,2和34;
  •   
  • 此切片的2个不同数字是1和2.
  •   
     

输入2:

     

[53,800,0,0,0,356,8988,1,1]

     

结果2:答案为4,因为(1,4)的切片是最大的切片   数组的数量不超过两个。切片(2,5)   也是有效的,仍会得到4的结果。

     
      
  • 此切片中有4个项目是" 800,0,0,0"。
  •   
  • 此切片的2个不同数字是800和0。
  •   
     

包含不超过的数组的最大公共数组切片   Java中的两个不同的数字实现采用逗号分隔   STDIN中的数字数组和输出被写回控制台。

我提供的实现(如下)有效,但3个测试用例在HR中超时。很明显,HR隐藏了测试用例,因此我无法确切地看到超时被触发的条件甚至是超时的长度。 考虑到我的解决方案的渐近复杂性,我对超时并不感到惊讶。但我的问题是:我的解决方案怎么能改进?

提前感谢所有有帮助的人!

import java.io.*;
import java.lang.*;
import java.util.*;
import java.util.stream.*;

public class Solution {
    public static void main(String args[] ) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = br.readLine();
        List<Integer> inputSequence = parseIntegerSequence(line);
        int largestSliceSize = calculateLargestSlice(inputSequence);

        System.out.println(largestSliceSize);
    }

    private static List<Integer> parseIntegerSequence(String input) {
        if (input == null)
            return new ArrayList();

        return Arrays.asList(input.split("\\s*,\\s*"))
                .stream()
                .filter(item -> item.matches("^\\s*-?[0-9]+\\s*$"))
                .map(item -> Integer.parseInt(item))
                .collect(Collectors.toList());
    }

    private static int calculateLargestSlice(List<Integer> inputSequence) {

        Map<Integer, Integer> temporaryMap = new HashMap<>();

        int result = 0;
        int startIndex = 0;
        int uniqueItemCount = 0;

        Integer[] array = inputSequence.toArray(new Integer[inputSequence.size()]);

        while (startIndex < array.length) { // loop over the entire input sequence
            temporaryMap.put(array[startIndex], startIndex);
            uniqueItemCount++;

            for (int j = startIndex + 1; j < array.length; j++) {
                if (temporaryMap.get(array[j]) == null) {
                    if (uniqueItemCount != 2) {
                        temporaryMap.put(array[j], j);

                        uniqueItemCount++;
                        if (j == array.length - 1) {
                            result = Math.max(result, j - startIndex + 1);
                            startIndex = array.length;
                            break;
                        }
                    } else {
                        result = Math.max(result, j - startIndex);
                        int item = array[j-1];
                        int firstFoundIndex = 0;
                        for( int k=j-1; k>=0; k-- )
                        {
                            if( array[k] != item )
                            {
                                firstFoundIndex = k+1;
                                break;
                            }
                        }
                        startIndex = firstFoundIndex;
                        temporaryMap.clear();
                        uniqueItemCount = 0;
                        break;
                    }
                } else if (temporaryMap.get(array[j]) != null) {
                    if (j == array.length - 1) {
                        result = Math.max(result, j - startIndex + 1);
                        startIndex = array.length;
                        break;
                    }
                }
            }
        }
        return result;
    }
}

2 个答案:

答案 0 :(得分:0)

这是我在Java中的答案,它通过了所有HackerRank测试用例。如果您发现错误,请随时发表评论。

{{1}}

答案 1 :(得分:-1)

根据OP

的要求,这是一个python解决方案
def solution(arr):
    if (len(arr) <= 2): print arr 
    lres = 0 
    rres = 0
    l = 0
    r = 1 
    last = arr[1]
    prev = arr[0]
    while(r <= len(arr)-1):
        if prev != last:
            if arr[r] == prev:
                prev = last
                last = arr[r]               
            elif arr[r] != last:
                l = r-1
                while(arr[l-1] == last):
                    l -= 1
                last = arr[r] 
                prev = arr[r-1]             
        else:
            if arr[r] != prev:
                last = arr[r]
        if r - l > rres-lres:
            rres = r
            lres = l
        r += 1
    print arr[lres:rres+1]

对于当前细分,我们假设last是最后添加的值,prev是细分中的第二个不同值。 (最初他们可能是平等的。)

让我们将指针lr保持在当前细分的左右两端,最多有两个不同的元素。我们假设我们考虑元素arr[r]。 如果当前细分[l,r-1]仅包含一个不同的元素,我们可以安全地添加arr[r],可能会更新lastprev。 现在,如果arr[r]等于last,那么我们就不需要做任何事情了。如果arr[r]等于prev,我们需要交换prevlast。如果它与这两者都不相等,我们需要更新l左指针,从r-1追溯到我们找到一个不等于last的元素,然后更新{{ 1}}和last