1. 程式人生 > >LeetCode周賽#107 Q3 Three Equal Parts

LeetCode周賽#107 Q3 Three Equal Parts

題目來源:https://leetcode.com/contest/weekly-contest-107/problems/three-equal-parts/

問題描述

927. Three Equal Parts

Given an array A of 0s and 1s, divide the array into 3 non-empty parts such that all of these parts represent the same binary value.

If it is possible, return any 

[i, j] with i+1 < j, such that:

  • A[0], A[1], ..., A[i] is the first part;
  • A[i+1], A[i+2], ..., A[j-1] is the second part, and
  • A[j], A[j+1], ..., A[A.length - 1] is the third part.
  • All three parts have equal binary value.

If it is not possible, return 

[-1, -1].

Note that the entire part is used when considering what binary value it represents.  For example, [1,1,0] represents 6 in decimal, not 3.  Also, leading zeros are allowed, so [0,1,1] and [1,1] represent the same value.

 

Example 1:

Input: [1,0,1,0,1]
Output: [0,3]

Example 2:

Input: [1,1,0,1,1]
Output: [-1,-1]

 

Note:

  1. 3 <= A.length <= 30000
  2. A[i] == 0 or A[i] == 1

------------------------------------------------------------

題意

給定一個0和1組成的int陣列,問能否把這個陣列分成三個部分,使得每個部分組成的二進位制整數數值相等(忽略先導零)

------------------------------------------------------------

思路

一開始以為是個三分搜尋題,想了半天沒有想出來壓縮搜尋區間的條件,後來發現其實是個模擬題。J

注意到“每個部分組成的二進位制整數數值相等”有兩個必要不充分條件:

(1)每個部分含有1的個數相等

(2)每個部分末尾0的個數相等

抓住這兩個條件,很容易判斷出那些不可行的case,並且唯一確定那些可能可行的case中的分割點。再根據求出的分割點分別計算三個部分對應的二進位制整數值,就可以最終判斷是否可行。

O(n)演算法。

------------------------------------------------------------

程式碼

class Solution {
public:
    int cal_bin(vector<int>& A, int beg, int end)
    {
        int i, j = 1, ret = 0;
        for (i=end-1; i>=beg; i--)
        {
            ret += A[i]*j;
            j <<= 1;
        }
        return ret;
    }
    
    vector<int> threeEqualParts(vector<int>& A) {
        int i, len = A.size(), cnt1 = 0, cnt = 0, m1 = -1, m2 = -1, tail0 = 0, lv, mv, rv;
        vector<int> ans;
        for (i=0; i<len; i++)
        {
            cnt1 += A[i];           // cnt1: # of '1's in vector A
        }
        if (cnt1 == 0)
        {
            ans.push_back(0);
            ans.push_back(2);
            return ans;
        }
        else if (cnt % 3 != 0)
        {
            ans.push_back(-1);
            ans.push_back(-1);
            return ans;
        }
        else
        {
            cnt = 0;
            tail0 = 0;              // tail0: # of '0's behind last '1', also # of '0's at the end of third binary number
            for (i=0; i<len; i++)
            {
                cnt += A[i];
                if (m1 == -1 && cnt == cnt1/3)
                {
                    m1 = i;         // possible end of second binary number
                }
                else if (m2 == -1 && cnt == cnt1*2/3)
                {
                    m2 = i;         // possible end of third binary number
                }
                else if (cnt == cnt1 && A[i] == 0)
                {
                    tail0++;
                }
            }
            for (i=m1+1; i <= m1 + tail0; i++)
            {
                if (A[i] == 1)      // not enough '0's at the end of first binary number
                {
                    ans.push_back(-1);
                    ans.push_back(-1);
                    return ans;
                }
            }
            for (i=m2+1; i<=m2+tail0; i++)
            {
                if (A[i] == 1)      // not enough '0's at the end of second binary number
                {
                    ans.push_back(-1);
                    ans.push_back(-1);
                    return ans;
                }
            }
            m1 += tail0;
            m2 += tail0;
            lv = cal_bin(A, 0, m1+1);
            mv = cal_bin(A, m1+1, m2+1);
            rv = cal_bin(A, m2+1, len);
            if (lv == mv && mv == rv)
            {
                ans.push_back(m1);
                ans.push_back(m2+1);
            }
            else
            {
                ans.push_back(-1);
                ans.push_back(-1);    
            }
            return ans;
        }
    }
};