顺序遍历,数组求和,求解《927. 三等分》

例题

927. 三等分

给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分 ,使得所有这些部分表示相同的二进制值。
如果可以做到,请返回任何 [i, j],其中 i+1 < j,这样一来:
arr[0], arr[1], ..., arr[i] 为第一部分;
arr[i + 1], arr[i + 2], ..., arr[j - 1] 为第二部分;
arr[j], arr[j + 1], ..., arr[arr.length - 1] 为第三部分。
这三个部分所表示的二进制值相等。
如果无法做到,就返回 [-1, -1]。
注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体。例如,[1,1,0] 表示十进制中的 6,而不会是 3。此外,前导零也是被允许的,所以 [0,1,1] 和 [1,1] 表示相同的值。
示例 1:
输入:arr = [1,0,1,0,1]
输出:[0,3]
示例 2:
输入:arr = [1,1,0,1,1]
输出:[-1,-1]
示例 3:
输入:arr = [1,1,0,0,1]
输出:[0,2]
提示:
3 <= arr.length <= 3 * 104
arr[i] 是 0 或 1

答案

顺序遍历

var threeEqualParts = function(arr) {
  const n = arr.length, sum = _.sum(arr)
  if (sum === 0) return [0, 2]
  if (sum % 3 !== 0) return [-1, -1]
  const avg = _.sum(arr) / 3
  let first = 0, second = 0, third = 0
  for (let i = 0, sum = 0; i < n; i++) {
    if (arr[i]) {
      if (sum === 0) first = i
      else if (sum === avg) second = i
      else if (sum === avg << 1) {
        third = i
        break
      }
      sum += arr[i]
    }
  }
  const len = n - third
  if (first + len > second || second + len > third) return [-1, -1]
  for (let i = 1; i < len; i++) {
    if (arr[first + i] !== arr[second + i] || arr[second + i] !== arr[third + i]) return [-1, -1]
  }
  return [first + len - 1, second + len]
};
var threeEqualParts = function(arr) {
  const n = arr.length
  let sum = 0
  for (let i = 0; i < n; i++) sum += arr[i]
  if (sum === 0) return [0, 2]
  if (sum % 3 !== 0) return [-1, -1]
  const avg = sum / 3
  let first = 0, second = 0, third = 0
  for (let i = 0, sum = 0; i < n; i++) {
    if (arr[i]) {
      if (sum === 0) first = i
      else if (sum === avg) second = i
      else if (sum === avg << 1) {
        third = i
        break
      }
      sum += arr[i]
    }
  }
  const len = n - third
  if (first + len > second || second + len > third) return [-1, -1]
  for (let i = 1; i < len; i++) {
    if (arr[first + i] !== arr[second + i] || arr[second + i] !== arr[third + i]) return [-1, -1]
  }
  return [first + len - 1, second + len]
};
function threeEqualParts(arr: number[]): number[] {
  const n = arr.length
  let sum = 0
  for (let i = 0; i < n; i++) sum += arr[i]
  if (sum === 0) return [0, 2]
  if (sum % 3) return [-1, -1]
  const avg = sum / 3
  let first = 0, second = 0, third = 0
  for (let i = 0, sum = 0; i < n; i++) {
    if (arr[i] === 0) continue 
    if (sum === 0) first = i
    else if (sum === avg) second = i
    else if (sum === avg << 1) {
      third = i
      break
    }
    sum += arr[i]
  }
  const len = n - third
  if (first + len > second || second + len > third) return [-1, -1]
  for (let i = 1; i < len; i++) {
    if (arr[first + i] !== arr[second + i] || arr[second + i] !== arr[third + i]) return [-1, -1]
  }
  return [first + len - 1, second + len]
};
class Solution {
  function threeEqualParts($arr) {
    $sum = array_sum($arr);
    if ($sum === 0) return [0, 2];
    if ($sum % 3) return [-1, -1];
    $avg = $sum / 3;
    $total = 0;
    $first = $second = $third = 0;
    foreach ($arr as $i => $num) {
      if ($num === 0) continue;
      if ($total === 0) $first = $i;
      elseif ($total === $avg) $second = $i;
      elseif ($total === $avg << 1) {
        $third = $i;
        break;
      }
      $total += $num;
    }
    $len = count($arr) - $third;
    if ($first + $len > $second || $second + $len > $third) return [-1, -1];
    for ($i = 1; $i < $len; $i++) {
      if ($arr[$first + $i] !== $arr[$second + $i] || $arr[$second + $i] !== $arr[$third + $i]) return [-1, -1];
    }
    return [$first + $len - 1, $second + $len];
  }
}
func threeEqualParts(arr []int) []int {
  sum := 0
  for _, num := range arr {
    sum += num
  }
  if sum == 0 {
    return []int{0, 2}
  }
  if sum % 3 != 0 {
    return []int{-1, -1}
  }
  first, second, third, total, avg := 0, 0, 0, 0, sum / 3
  label: for i, num := range arr {
    if num == 0 {
      continue
    }
    switch total {
      case 0:
        first = i
      case avg:
        second =  i
      case avg << 1:
        third = i
        break label
    }
    total += num
  }
  size := len(arr) - third
  if first + size > second || second + size > third {
    return []int{-1, -1}
  }
  for i := 1; i < size; i++ {
    if arr[first + i] != arr[second + i] || arr[second + i] != arr[third + i] {
      return []int{-1, -1}
    }
  }
  return []int{first + size - 1, second + size}
}
class Solution {
  public int[] threeEqualParts(int[] arr) {
    int sum = Arrays.stream(arr).sum();
    if (sum == 0) return new int[]{0, 2};
    if (sum % 3 > 0) return new int[]{-1, -1};
    int avg = sum / 3, first = 0, second = 0, third = 0, total = 0;
    int n = arr.length;
    for (int i = 0; i < n; i++) {
      if (arr[i] == 0) continue;
      if (total == 0) first = i;
      else if (total == avg) second = i;
      else if (total == avg << 1) {
        third = i;
        break;
      }
      total += arr[i];
    }
    int len = n - third;
    if (first + len > second || second + len > third) return new int[]{-1, -1};
    for (int i = 1; i < len; i++) {
      if (arr[first + i] != arr[second + i] || arr[second + i] != arr[third + i]) return new int[]{-1, -1};
    }
    return new int[]{first + len - 1, second + len};
  }
}
public class Solution {
  public int[] ThreeEqualParts(int[] arr) {
    int sum = arr.Sum();
    if (sum == 0) return new int[]{0, 2};
    if (sum % 3 > 0) return new int[]{-1, -1};
    int avg = sum / 3, first = 0, second = 0, third = 0, total = 0, n = arr.Length;
    for (int i = 0; i < n; i++) {
      if (arr[i] == 0) continue;
      if (total == 0) first = i;
      else if (total == avg) second = i;
      else if (total == avg << 1) {
        third = i;
        break;
      }
      total += 1;
    }
    int len = n - third;
    if (first + len > second || second + len > third) return new int[]{-1, -1};
    for (int i = 1; i < len; i++) {
      if (arr[first + i] != arr[second + i] || arr[second + i] != arr[third + i]) return new int[]{-1, -1};
    }
    return new int[]{first + len - 1, second + len};
  }
}
int* threeEqualParts(int* arr, int arrSize, int* returnSize){
  int sum = 0;
  int* r = malloc(sizeof(int) * 2);
  *returnSize = 2;
  memset(r, -1, sizeof(int) * 2);
  for (int i = 0; i < arrSize; i++) sum += arr[i];
  if (sum == 0) {
    r[0] = 0;
    r[1] = 2;
    return r;
  }
  if (sum % 3) return r;
  int avg = sum / 3, first = 0, second = 0, third = 0, total = 0;
  for (int i = 0; i < arrSize; i++) {
    if (arr[i] == 0) continue;
    if (total == 0) first = i;
    else if (total == avg) second = i;
    else if (total == avg << 1) {
      third = i;
      break;
    }
    total += 1;
  }
  int len = arrSize - third;
  if (first + len > second || second + len > third) return r;
  for (int i = 1; i < len; i++) {
    if (arr[first + i] != arr[second + i] || arr[second + i] != arr[third + i]) return r;
  }
  r[0] = first + len - 1;
  r[1] = second + len;
  return r;
}
class Solution {
public:
  vector<int> threeEqualParts(vector<int>& arr) {
    int sum = accumulate(arr.begin(), arr.end(), 0);
    if (sum == 0) return {0, 2};
    if (sum % 3) return {-1, -1};
    int avg = sum / 3, first = 0, second = 0, third = 0, total = 0, n = arr.size();
    for (int i = 0; i < n; i++) {
      if (arr[i] == 0) continue;
      if (total == 0) first = i;
      else if (total == avg) second = i;
      else if (total == avg << 1) {
        third = i;
        break;
      }
      total += 1;
    }
    int len = n - third;
    if (first + len > second || second + len > third) return {-1, -1};
    for (int i = 1; i < len; i++) {
      if (arr[first + i] != arr[second + i] || arr[second + i] != arr[third + i]) return {-1, -1};
    }
    return {first + len - 1, second + len};
  }
};
class Solution:
  def threeEqualParts(self, arr: List[int]) -> List[int]:
    summation = sum(arr)
    if summation == 0: return [0, 2]
    if summation % 3: return [-1, -1]
    avg, first, second, third, total = summation / 3, 0, 0, 0, 0
    for i, num in enumerate(arr):
      if num == 0: continue
      if total == 0: first = i
      elif total == avg: second = i
      elif total == int(avg) << 1:
        third = i
        break
      total += 1
    size = len(arr) - third
    if first + size > second or second + size > third: return [-1, -1]
    for i in range(1, size):
      if arr[first + i] != arr[second + i] or arr[second + i] != arr[third + i]: return [-1, -1]
    return [first + size - 1, second + size]

栈、顺序遍历,为可变数组添加元素,2 解法求解《1441. 用栈操作构建数组》
栈、顺序遍历,为可变数组添加元素,2 解法求解《1441. 用栈操作构建数组》
动态规划,求解《940. 不同的子序列 II》
动态规划,求解《940. 不同的子序列 II》
贪心算法,求解《769. 最多能完成排序的块》
贪心算法,求解《769. 最多能完成排序的块》