O(N) solution in Rust (4ms).
The algorithm proceeds as follows:\n- find the number of 1s that each part must have. This number must be total_number_of_ones/3 sinceo otherwise parts would de
The algorithm proceeds as follows:\n- find the number of `1`s that each part must have. This number must be `total_number_of_ones/3` sinceo otherwise parts would definitely not have same values. Because of this if the total number of `1`s is not a multiple of `3`, we can return `{-1, -1}` immediately. Another simple optimization that can be made at this stage is checking if the total number of `1`s is `0`, since in such case any split would result in equal parts. I use `{0,2}` just because it works for all input sizes, including `3`.\n- find the number of trailing zeros. Since in order to have same values all numbers have to have the exact same number of trailing zeros, we can use the last part to get it, since we know that the end of the thrird part is `A.length-1`.\n- find the end of the first part. To do this we increase the index until we find encounter `part_ones` number of `1`s and then will skip `trailing_zeros` after making sure that there are enough trailing zeros available.\n- find the end of the second part. The procedure is exactly the same as the one used for the first part, but the scan starts with `i+1`.\n- check if all parts are equal and if not return `{-1, -1}`. I\'m relying on iterator `zip` method to stop as soon as one of the ranges is exhausted in order to avoid having to deal with different part lengths.\n- return the end of the first and the start of the third part (one past the end of the second part).\n\n```\nimpl Solution {\n    pub fn three_equal_parts(a: Vec<i32>) -> Vec<i32> {\n        let ones = a.iter().filter(|&n| *n == 1).count();\n        if ones == 0 {\n            return vec![0, 2]; // any split works here\n        }\n        if ones % 3 != 0 {\n            return vec![-1, -1];\n        }\n        let part_ones = ones / 3;\n        let trailing_zeros = (0..a.len()).rev().take_while(|&idx| a[idx] == 0).count();\n        \n        let find_part_end = |start| -> Option<usize> {\n            let mut ones = 0;\n            let mut i = start;\n            while ones < part_ones {\n                if a[i] == 1 {\n                    ones += 1;\n                }\n                i += 1;\n            }\n            if !(i..(i+trailing_zeros)).all(|idx| a[idx] == 0) {\n                // first part does not have enough trailing zeros\n                return None;\n            }\n            Some(i + trailing_zeros - 1)\n        };\n        \n        let i = match find_part_end(0) { // first part end\n            Some(i) => i,\n            None => return vec![-1, -1],\n        };\n        \n        let j = match find_part_end(i+1) { // second part end\n            Some(j) => j + 1, // j starts after the end of second part\n            None => return vec![-1, -1],\n        };\n        \n        if !(0..i+1).rev().zip((i+1..j).rev()).all(|t| a[t.0] == a[t.1]) {\n            // first and second parts are different\n            return vec![-1, -1];\n        }\n        \n        if !(i+1..j).rev().zip((j..a.len()).rev()).all(|t| a[t.0] == a[t.1]) {\n            // second and first parts are different\n            return vec![-1, -1];\n        }\n        \n        vec![i as i32, j as i32]\n    }\n}\n```
[]