美文网首页
阿里巴巴2017实习生春招编程测验 —— 数组四等分

阿里巴巴2017实习生春招编程测验 —— 数组四等分

作者: stevewang | 来源:发表于2017-07-30 16:57 被阅读86次

    对于一个长度为N的整型数组A, 数组里所有的数都是正整数,对于两个满足0 <= X <= Y < N的整数,A[X], A[X+1] … A[Y]构成A的一个切片,记作(X, Y).
    用三个下标 m1, m2, m3(下标满足条件0 < m1, m1 + 1 < m2, m2 +1 < m3 < N – 1)可以把这个整型数组分成(0, m1-1), (m1+1, m2-1), (m2+1, m3-1), (m3+1, N-1) 四个切片。
    如果这四个切片的整数求和相等,称作“四等分”。

    编写一个函数,求一个给定的整型数组是否可以四等分,如果可以,返回一个布尔类型的true,如果不可以返回一个布尔类型的false。
    限制条件:数组A最多有1,000,000项,数组中的整数取值范围介于-1,000,000到1,000,000之间。
    要求:函数的计算复杂度为O(N),使用的额外存储空间(除了输入的数组之外)最多为O(N)。

    例子:
    对于数组A=[2, 5, 1, 1, 1, 1, 4, 1, 7, 3, 7] 存在下标 2, 7, 9使得数组分成四个分片[2, 5], [1, 1, 1, 4], [7], [7],这三个分片内整数之和相等,所以对于这个数组,函数应该返回true。
    对于数组 A=[10, 2, 11, 13, 1, 1, 1, 1, 1],找不到能把数组四等分的下标,所以函数应该返回false。

    今年参加了阿里的实习生春招,在进行编程测验之前已经了解到部分同学遇到的是这道题,所以事先做了准备,然而轮到我时已经换题了,可能是不同岗位题目不一样吧。

    这道题描述的啰哩啰嗦,实际上就是给一个全是正数的数组,问是否能将该数组分割成四部分,每一部分累加和相等,分割点不算

    要解决这题首先要明确数组四等分的结构,即3个分割点,4个切片,有了这个概念,在草纸上画画,问题很容易就解决了。

    首先我们遍历一遍数组构造一个HashMap存储 ( arr[i]左边所有元素的和 , i ) ,然后大多数人选择让分割点m1、m3从两端像中间移动的同时累加两个切片内元素(谁小谁移动),当两个切片相等时根据四等分结构看能否找到满足条件的分割点m2。

    这里我选择仅将分割点m1由左向右移动,如果数组可以四等分,依据3个分割点,4个切片这样一个基本结构,一旦分割点m1确定了,m2、m3也就相应确定了,如果最后找不到符合基本结构的m2、m3,则可以断定数组不可以四等分,时间复杂度O(N),代码如下:

    public static boolean canSplits(int[] arr) {
        if (arr == null || arr.length < 7) {    // 元素个数小于7,无法构成3个分割点、4个切片的基本结构
            return false;
        }
        HashMap<Long, Integer> leftSumToIndex = new HashMap<>();
        Long sum = (long) arr[0];
        for (int i = 1; i < arr.length; i++) {
            leftSumToIndex.put(sum, i);    // 把(arr[i]左边所有元素的和, i)存入HashMap
            sum += arr[i];
        }
        Long part = (long) arr[0];         // part为切片内元素的和
        for (int m1 = 1; m1 < arr.length - 5; m1++) {   // 遍历分割点m1
            Long m2LeftSum = part + arr[m1] + part;     // 分割点m2左边所有元素的和
            if (leftSumToIndex.containsKey(m2LeftSum)) {
                int m2 = leftSumToIndex.get(m2LeftSum);
                Long m3LeftSum = m2LeftSum + arr[m2] + part;  // 分割点m3左边所有元素的和
                if (leftSumToIndex.containsKey(m3LeftSum)) {
                    int m3 = leftSumToIndex.get(m3LeftSum);
                    if (m3LeftSum + arr[m3] + part == sum) {
                        return true;
                    }
                }
            }
            part += arr[m1];
        }
        return false;
    }
    

    对于像Two SumLongest Substring Without Repeating Characters以及本题这种涉及数组下标的一系列问题,优先考虑事先构造一个HashMap看是否对后续的求解有帮助。在HashMap中,每次查询操作的时间复杂度均为O(1),所以它一直是编写高效算法的利器。

    相关文章

      网友评论

          本文标题:阿里巴巴2017实习生春招编程测验 —— 数组四等分

          本文链接:https://www.haomeiwen.com/subject/utfklxtx.html