2023-03-16:给定一个由 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] 表示相同的值。
输入:arr = [1,0,1,0,1],
输出:[0,3]。
输入:arr = [1,1,0,0,1],
输出:[0,2]。

答案2023-03-16:

给定一个由 0 和 1 组成的数组 arr,需要将其分成三个非空部分,使得每个部分中 1 的数量相等。如果无法做到,则返回 [-1, -1]。

输入:由 0 和 1 组成的数组 arr,长度为 n(1 ≤ n ≤ 3×10^4),且只包含数字 0 和 1。

输出:长度为 2 的数组,表示能够将 arr 分成三个部分时第一个和第二个部分的结束位置(下标从 0 开始)。如果无法做到则返回 [-1, -1]。

解法思路:

首先统计整个数组中 1 的数量 ones,如果 ones 不能被 3 整除,则说明无法分成三个相等的部分,直接返回 [-1, -1]。

如果 ones 等于 0,则整个数组都是 0,可以返回 [0, n-1]。

接着需要找到第一个、第二个和第三个部分的起始位置。根据题意,第一个部分和第二个部分的 1 的数量应该是 ones/3,因此可以先计算出目标值 part = ones/3,然后从左到右遍历整个数组,在找到第一个和第二个部分之后,继续遍历找到第三个部分的起始位置。

接下来检查第三个部分是否也等于目标值 part。如果是,则返回 [end1, end2],否则返回 [-1, -1]。

代码实现:

fn main() {
let arr1 = vec![0, 0, 0, 0, 0];
println!("{:?}", three_equal_parts(arr1)); // [0, 4] let arr2 = vec![1, 0, 1, 0, 1, 0];
println!("{:?}", three_equal_parts(arr2)); // [1, 4] let arr3 = vec![1, 0, 1, 0, 1];
println!("{:?}", three_equal_parts(arr3)); // [0, 3] let arr4 = vec![1, 0, 1, 1, 1];
println!("{:?}", three_equal_parts(arr4)); // [-1, -1] let arr5 = vec![0, 1, 0, 1, 0, 1, 0, 1, 0, 1];
println!("{:?}", three_equal_parts(arr5)); // [-1, -1] let arr6 = vec![1, 1, 0, 1, 1, 0, 1, 1];
println!("{:?}", three_equal_parts(arr6)); // [1, 5]
} pub fn three_equal_parts(arr: Vec<i32>) -> Vec<i32> {
let ones = arr.iter().filter(|&num| *num == 1).count(); // 统计数组中 1 的个数
if ones % 3 != 0 {
// 如果无法分成三个相等的部分,则返回 [-1, -1]
return vec![-1, -1];
}
let n = arr.len();
if ones == 0 {
// 如果整个数组都是 0,则返回 [0, n-1]
return vec![0, n as i32 - 1];
}
let part = ones / 3; // 计算每个子数组中 1 的数量
let mut start1 = -1; // 第一个子数组的起始位置
let mut start2 = -1; // 第二个子数组的起始位置
let mut start3 = -1; // 第三个子数组的起始位置
let mut cnt = 0; // 当前已经遇到的 1 的数量
for i in 0..n {
if arr[i] == 1 {
cnt += 1;
if start1 == -1 && cnt == 1 {
start1 = i as i32; // 找到第一个子数组的起始位置
}
if start2 == -1 && cnt == part + 1 {
start2 = i as i32; // 找到第二个子数组的起始位置
}
if start3 == -1 && cnt == 2 * part + 1 {
start3 = i as i32; // 找到第三个子数组的起始位置
}
}
}
while start3 < n as i32 {
if arr[start1 as usize] != arr[start2 as usize]
|| arr[start1 as usize] != arr[start3 as usize]
{
return vec![-1, -1]; // 如果找到的三个子数组不相等,则返回 [-1, -1]
}
start1 += 1;
start2 += 1;
start3 += 1;
}
vec![start1 - 1, start2] // 返回第一个和第二个子数组的结束位置
}

算法分析:

该算法的时间复杂度为 O(n),其中 n 是输入数组的长度,因为需要遍历整个数组一次。空间复杂度为 O(1),只需要常量级别的额外空间存储一些变量。该算法的优点是简单易懂,缺点是可能会超时,比如当输入数组中有很多连续的 1 时。可以通过进一步优化算法来提高效率。

测试结果:

1.测试用例:[0,0,0,0,0],预期输出:[0, 4]。

assert_eq!(three_equal_parts(vec![0,0,0,0,0]), vec![0, 4]);

2.测试用例:[1, 0, 1, 0, 1, 0],预期输出:[1, 4]。

assert_eq!(three_equal_parts(vec![1, 0, 1, 0, 1, 0]), vec![1, 4]);

3.测试用例:[1, 0, 1, 0, 1],预期输出:[0, 3]。

assert_eq!(three_equal_parts(vec![1, 0, 1, 0, 1]), vec![0, 3]);

4.测试用例:[1, 0, 1, 1, 1],预期输出:[-1, -1]。

assert_eq!(three_equal_parts(vec![1, 0, 1, 1, 1]), vec![-1, -1]);

5.测试用例:[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],预期输出:[-1, -1]。

assert_eq!(three_equal_parts(vec![0, 1, 0, 1, 0, 1, 0, 1, 0, 1]), vec![-1, -1]);

6.测试用例:[1, 1, 0, 1, 1, 0, 1, 1],预期输出:[1, 5]。

assert_eq!(three_equal_parts(vec![1, 1, 0, 1, 1, 0, 1, 1]), vec![1, 5]);

总结和展望:

本文介绍了一种简单的算法,可以解决给定一个由 0 和 1 组成的数组 arr,需将其分成三个非空部分,使得每个部分中 1 的数量相等的问题。该算法的核心思路是计算目标值 target_val,并在遍历整个数组两次的过程中找到第一个和第二个部分的结束位置 i 和 j。该算法的时间复杂度为 O(n),空间复杂度为 O(1)。

有一些情况下该算法可能会超时,比如当输入数组中有很多连续的 1 时。可以通过进一步优化算法来提高效率。例如,可以使用双指针来记录第一个和第二个部分的结束位置,从而减少遍历数组的次数。另外,可以使用位运算来加速计算当前部分的二进制数值。

2023-03-16:给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分, 使得所有这些部分表示相同的二进制值。 如果可以做到,请返回任何 [i, j],其中 i+1 < j的更多相关文章

  1. 2018/03/16 每日一个Linux命令 之 rm

    最痛快的指令,没有之一. 一次永久删除,恢复很麻烦. 我会告诉你我第一次上服务器的时候删除了项目代码?(还好我提前备份了一下) -- rm [-参数][文件或者文件夹/支持正则通配] 参数: -i 删 ...

  2. 现在有一个城市销售经理,需要从公司出发,去拜访市内的商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他只能在左右中选择一个方向,在上下中选择一个方向,现在问他有多少种方案到达商家地址。给定一个地图map及它的长宽n和m,其中1代表经理位置,2代表商家位置,-1代表不能经过的地区,0代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于10。

    include "stdafx.h" #include<iostream> #include<vector> #include<algorithm&g ...

  3. 有一个长为n的数组A,求满足0≤a≤b<n的A[b]-A[a]的最大值。 给定数组A及它的大小n,请返回最大差值。

    // ConsoleApplication10.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream& ...

  4. 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。

    /** * 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标. * * 你可以假设每种输入只会对应一个答案.但是,数组中 ...

  5. 谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。

    谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数. Google2009华南地 ...

  6. 给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回

    给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回 //统计字符串中出现的字符的出现次数 public function strNum(){ ...

  7. 给定一个double类型的数组arr,其中的元素可正可负可0,返回子数组累乘的最大乘积。例如arr=[-2.5,4,0,3,0.5,8,-1],子数组[3,0.5,8]累乘可以获得最大的乘积12,所以返回12。

    分析,是一个dp的题目, 设f[i]表示以i为结尾的最大值,g[i]表示以i结尾的最小值,那么 f[i+1] = max{f[i]*arr[i+1], g[i]*arr[i+1],arr[i+1]} ...

  8. 基础作业 本周没上课,但是请大家不要忘记学习。 本周请大家完成上周挑战作业的第一部分:给定一个整数数组(包含正负数),找到一个具有最大和的子数组,返回其最大的子数组的和。 例如:[1, -2, 3, 10, -4, 7, 2, -5]的最大子数组为[3, 10, -4, 7, 2] 输入: 请建立以自己英文名字命名的txt文件,并输入数组元素数值,元素值之间用逗号分隔。 输出 在不删除原有文件内容

    1丶 实验代码 #include<stdio.h> int main(void) { int tt,nn,i,j,c[11][11]; int flag=1; scanf("%d ...

  9. 给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 ,返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况)

    """ #给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 #返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况) 解题思路: 1.设定一个 ...

  10. 最短路径(给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动一步。)

    给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 例: 输入: [ [1,3,1], [1,5,1], [ ...

随机推荐

  1. Fastboot_Cmd

    /* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- */adb命令:/* -*-* ...

  2. 文件的上传&预览&下载学习(四)

    0.参考博客 https://blog.csdn.net/Chengzi_comm/article/details/53037967 逻辑清晰 https://blog.csdn.net/alli09 ...

  3. vue2升级vue3:vue-i18n国际化异步按需加载

    vue2异步加载之前说过,vue3还是之前的方法,只是把 i18n.setLocaleMessage改为i18n.global.setLocaleMessage 但是本文还是详细说一遍: 为什么需要异 ...

  4. Ocelot的限流、熔断和负载均衡

    一.限流 想要在Ocelot中设置限流,需要在设置如下绿色所示: { "GlobalConfiguration": { "RateLimitOptions": ...

  5. java网络编程--4 UDP

    java网络编程--4 UDP 1.7.UDP 发短信:不用连接,但是需要知道对方的地址 主要包含两个类:DatagramPacket 和 DatagramSocket 发送消息 发送端: packa ...

  6. Java面试——消息队列

    一.消息队列的使用场景 ☞ 以下介绍消息队列在实际应用常用的使用场景.异步处理.应用解耦.流量削锋和消息通讯四个场景.[1]异步处理:场景说明:用户注册后,需要发注册邮件和注册短信.  引入消息队列后 ...

  7. wx相关

    1.vue图片预览放大 https://www.jianshu.com/p/e3350aa1b0d0 2.js图片文件格式的转换 https://www.jianshu.com/p/ea757f90b ...

  8. 2020寒假学习笔记12------Python基础语法学习(一)

    代码的组织和缩进 Python 语言直接通过缩进来组织 代码块."缩进"成为了 Python 语法强制的规定.缩进时,几个空格都是允许的,但是数目必须统一.我们通常采用" ...

  9. LeetCode刷题笔记 - 2022

    这篇博客集中整理在LeetCode的刷题记录,方便查阅 258. 各位相加 - 力扣(LeetCode) (leetcode-cn.com) 代码 class Solution { public: i ...

  10. 基于docker和cri-dockerd部署k8sv1.26.3

    cri-dockerd是什么? 在 Kubernetes v1.24 及更早版本中,我们使用docker作为容器引擎在k8s上使用时,依赖一个dockershim的内置k8s组件:k8s v1.24发 ...