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. WordPress标题分隔符”-“被转义为“&#8211”怎么办?

    按照百度搜索资源平台<百度搜索网页标题规范:让标题回归标题本身>百度官方文档参考,如果WordPress标题里出现不规范"– 2.停止wptexturize转义任何字符 add_ ...

  2. ubuntu主机连接家里的网线

    第一步,先让物理机连接网络: 注释掉/etc/network/interfaces文件的最后一行,即: 意思是不要手动设置网络了,而是转为自动设置.这样,主机就可以联网了. 参考链接:https:// ...

  3. Fastboot_Cmd

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

  4. You need to run build with JDK or have tools.jar on the classpath.If this occures during eclipse build make sure you run eclipse under JDK as well 错误

    我打开项目报错是这样的  pom.xml jdk配置什么的都是好的    但是还是报错 解决错误 : 1.打开你eclipse的根目录,找到eclipse.ini  这个文件夹打开 2.打开是这个样子 ...

  5. MySQL学习(十三)InnoDB

    参考博客: https://my.oschina.net/wangzemin/blog/5346534 InnoDB之BufferPool https://juejin.cn/post/7007421 ...

  6. Spring Boot中如何优雅地实现异步调用?

    前言 SpringBoot想必大家都用过,但是大家平时使用发布的接口大都是同步的,那么你知道如何优雅的实现异步呢? 这篇文章就是关于如何在Spring Boot中实现异步行为的.但首先,让我们看看同步 ...

  7. SpringBoot工程入门case

    SpringBoot的设计目的是用来简化Spring应用的初始搭建以及开发过程. SpringBoot入门案例: 1.创建一个新module 2.除pom和src文件剩余都删除. 3.在src.com ...

  8. ChatGPT 何许人也

    有时候会想,如果chatGPT是人,它会是一个怎样的人呢?下面是我的推测过程. 首先,她应该是女人 会推测而不会计算 你问它: 3457 * 43216 = ,它回答 149261912 (这是错的. ...

  9. pip更新一直time out 的解决方法

    python -m pip install -U --force-reinstall pip 或者指定安装的镜像, 这里以安装numpy为例,运行pip install numpy -i http:/ ...

  10. 为什么HashMap查找比List快很多?

    做两数之和这道题目时,引发了一个思考: 为什么两者运行时间相差如此之大???好残忍,我List比你HashMap到底差在哪**** 于是我一顿查资料.... 战犯哈希算法登场 哈希算法会根据你要存入的 ...