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. 火狐浏览器调试eval源码

    火狐浏览器调试eval源码 firefox浏览器在网页调试上,有一个没法和chrome一比高下的功能,就是eval脚本的调试,有时前端架构使用了基于eval的方式,有时候可能是自己一个多行函数,每每遇 ...

  2. tcpdump在wlan抓包时的可用过滤器

    抓包前使用iw命令创建一个监听模式(monitor)的接口 iw phy phy0 interface add mon0 type monitor tcpdum抓包命令: tcpdump -nei m ...

  3. layui使用OSS上传

    1.首先要把aliyun-oss-sdk.js包下载下来,放到指定的目录下面  在要用的页面引入或者在index.html入口文件全局引入: <script src="util/ali ...

  4. Java面向对象 --2

    22.面向对象特征之二: 继  承     2020-04-29  21:39:33 01.多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么子类无需再定义这些属性和行为,只要继承父类即 ...

  5. mysql查询近N天的数据

    今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ...

  6. Redis内存淘汰策略

    目录 一.内存淘汰策略重要性 二.Key值过期策略 三.内存淘汰策略 三.Redis内存淘汰策略配置 一.内存淘汰策略重要性 我们都知道redis的性能很高,最主要的原因之一就是redis的数据都在内 ...

  7. Android笔记--Jetpack Room

    Jetpack Room 使用Room简化数据库操作:(基于SQLite) 在使用Room之前: 使用Room框架有以下几个步骤: 1.实体类加@Entity注解 @PrimaryKey(autoGe ...

  8. 阿里云镜像创建Spring Boot工厂

    参考博客:https://blog.csdn.net/qq_40052237/article/details/115794368 http://start.aliyun.com

  9. buildroot交叉编译ros过程中遇到的问题

    问题:Download error on https://pypi.python.org/simple/python-dateutil/:unknown url type:https --Some p ...

  10. scrcpy软件的使用

    一.scrcpy软件介绍: scrcpy是通过adb调试的方式来将手机屏幕投到电脑上,并可以通过电脑控制您的Android设备.它可以通过USB连接,也可以通过Wifi连接(类似于隔空投屏),而且不需 ...