subject
Given an array A consisting of 0 and 1, the array is divided into three non empty parts so that all parts represent the same binary value.
If you can, return any [i, j], where I + 1 < J, so that:
A [0], a [1],..., a [i] constitute the first part;
A [i + 1], a [i + 2],..., a [J-1] as the second part;
A [J], a [J + 1],..., a [a.length - 1] is the third part.
The three parts represent the same binary values.
If not, return [- 1, - 1].
Note that when considering the binaries represented by each part, it should be considered as a whole. For example, [1,1,0] means 6 in decimal, not 3. In addition, leading zeros are also 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:
Output: [1,1,0,1,1]
Output: [- 1, - 1]
Tips:
3 <= A.length <= 30000
A[i] == 0 or A[i] == 1
thinking
There are a few little tips that are not easy to find at a glance
- For the same value divided into three equal parts, the number of '1' should be the same, that is to say, in a given array, the number of '1' should be% 3 = = 0, otherwise it cannot be divided into three equal parts. The number of '1' in each copy that can be divided into three equal parts should be the number of '1' in the array divided by three.
- When we know the number of '1', we can determine the value of each copy. This value is unique. We can find it through the last copy: traverse the array from the back to the front, until the number of '1' is equal to the number of '1' in the array divided by three, and this binary number is the value of each copy. (this process can reserve the number of '0' suffixes for later use)
- After the value is determined, the array can be traversed from front to back. Similarly, the number of '1' can be found by the number of '1'. After the number of '1' is found, plus the suffix 0 just found, if the number of the following 0 does not find more than the suffix 0, it cannot be divided. If yes, find the value of this binary number, which is equal to the previous value, then this position is the value of i. if it is not equal, it cannot be divided. Repeat this step to get the value of j.
The time complexity of this method is O(n). If you have better solutions, or can optimize the place, welcome to leave a message.
code
func threeEqualParts(A []int) []int { var lA = len(A) -1 result := make([]int,0,2) ones := 0 for _, a := range A { if a == 1 { ones++ } } if ones % 3 != 0{ result = append(result, -1, -1) return result } partOnes := ones / 3 if partOnes == 0 { result = append(result, 0, 4) return result } tPartOnes := partOnes suffixZero := 0 flag := false realValue := 0 var tmpI, tmpJ int for i:=lA;i>0;i-- { // Determine the true value of suffix zero if !flag && A[i] == 0{ suffixZero++ } if A[i] == 1 { flag = true tPartOnes-- if tPartOnes == 0{ realValue = cal(A[i:]) tmpJ = i break } } } tmpI,ok := find(A[:tmpJ], partOnes, realValue, suffixZero) if ! ok { result = append(result, -1, -1) return result } tmpJ, ok = find(A[tmpI+1:tmpJ], partOnes, realValue, suffixZero) if ! ok { result = append(result, -1, -1) return result } tmpJ = tmpI+tmpJ+2 result = append(result, tmpI, tmpJ) return result } // It is used to find part 1 and Part 2. If it is found before, it will return to the current position func find(A []int, partOnes, realValue, suffixZero int) (i int, b bool) { l := len(A) -1 tmpI:=0 for i, a := range A { if a == 1 { partOnes-- if partOnes==0{ for j:=suffixZero;j>0;j--{ if i+j > l { return 0, false } if A[i+j] != 0{ return 0, false } } tmpI = i+suffixZero break } } } if cal(A[:tmpI+1]) != realValue { return 0, false } return tmpI, true } func cal(A []int) int { l := len(A) result := 0 for i, a := range A { result += a * ((l-i) * (l-i)) } return result }