2022-08-24:给定一个长度为3N的数组,其中最多含有0、1、2三种值, 你可以把任何一个连续区间上的数组,全变成0、1、2中的一种, 目的是让0、1、2三种数字的个数都是N。 返回最小的变化次
2022-08-24:给定一个长度为3N的数组,其中最多含有0、1、2三种值,
你可以把任何一个连续区间上的数组,全变成0、1、2中的一种,
目的是让0、1、2三种数字的个数都是N。
返回最小的变化次数。
来自京东。4.2笔试。
答案2022-08-24:
自然智慧即可。统计0,1,2扣去N/3的个数之和。
比如[1,1,1],1有3个,多了两个;而0和2都是0个,不统计;所以结果是2。
时间复杂度:O(N)。
代码用rust编写。代码如下:
use rand::Rng;
fn main() {
let n: i32 = 8;
let test_time: i32 = 2000;
println!("测试开始");
for _ in 0..test_time {
let m = (rand::thread_rng().gen_range(0, n) + 1) * 3;
let mut arr = random_array(m);
let ans1 = min_times1(&mut arr);
let ans2 = min_times2(&mut arr);
if ans1 != ans2 {
println!("出错了!");
break;
}
}
println!("测试结束");
}
const MAX_VALUE: i32 = 1 << 31 - 1;
// 暴力方法
// 为了验证不会超过2次
fn min_times1(arr: &mut Vec<i32>) -> i32 {
let mut set: Vec<i32> = vec![];
for _ in 0..arr.len() {
set.push(0);
}
for i in 0..arr.len() {
set[i] = arr[i];
}
return process1(&mut set, 0, arr);
}
fn process1(set: &mut Vec<i32>, time: i32, origin: &mut Vec<i32>) -> i32 {
let mut cnt: Vec<i32> = vec![];
for _ in 0..3 {
cnt.push(0);
}
for num in set.iter() {
cnt[*num as usize] += 1;
}
if cnt[0] == cnt[1] && cnt[0] == cnt[2] {
return time;
} else {
if time == 2 {
return 3;
}
let mut ans = MAX_VALUE;
for ll in 0..set.len() as i32 {
for rr in ll..set.len() as i32 {
set1(set, ll, rr, 0);
ans = get_min(ans, process1(set, time + 1, origin));
set1(set, ll, rr, 1);
ans = get_min(ans, process1(set, time + 1, origin));
set1(set, ll, rr, 2);
ans = get_min(ans, process1(set, time + 1, origin));
rollback(set, ll, rr, origin);
}
}
return ans;
}
}
fn set1(set: &mut Vec<i32>, ll: i32, rr: i32, v: i32) {
for i in ll..=rr {
set[i as usize] = v;
}
}
fn rollback(set: &mut Vec<i32>, ll: i32, rr: i32, origin: &mut Vec<i32>) {
for i in ll..=rr {
set[i as usize] = origin[i as usize];
}
}
fn get_max<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
}
fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a < b {
a
} else {
b
}
}
// 正式方法
// 时间复杂度O(N)
fn min_times2(arr: &mut Vec<i32>) -> i32 {
let mut cnt: Vec<i32> = vec![];
for _ in 0..3 {
cnt.push(0);
}
for num in arr.iter() {
cnt[*num as usize] += 1;
}
if cnt[0] == cnt[1] && cnt[0] == cnt[2] {
return 0;
}
let n = arr.len() as i32;
let m = n / 3;
if (cnt[0] < m && cnt[1] < m) || (cnt[0] < m && cnt[2] < m) || (cnt[1] < m && cnt[2] < m) {
return 2;
} else {
// 只有一种数的个数是小于m的
return if once(arr, &mut cnt, m) { 1 } else { 2 };
}
}
// 只有一种数是少于N/3
fn once(arr: &mut Vec<i32>, cnt: &mut Vec<i32>, m: i32) -> bool {
let less_v = if cnt[0] < m {
0
} else {
if cnt[1] < m {
1
} else {
2
}
};
let less_t = if less_v == 0 {
cnt[0]
} else {
if less_v == 1 {
cnt[1]
} else {
cnt[2]
}
};
if cnt[0] > m && modify(arr, 0, cnt[0], less_v, less_t) {
return true;
}
if cnt[1] > m && modify(arr, 1, cnt[1], less_v, less_t) {
return true;
}
if cnt[2] > m && modify(arr, 2, cnt[2], less_v, less_t) {
return true;
}
return false;
}
// 0 -> 10个
// 1 -> 10个
// 2 -> 10个
// ==========
// 0 -> 7个
// 2 -> 12个 1 -> 11个
// 多的数 2
// 少的数 0
fn modify(arr: &mut Vec<i32>, more: i32, more_t: i32, less: i32, less_t: i32) -> bool {
let mut cnt: Vec<i32> = vec![];
for _ in 0..3 {
cnt.push(0);
}
cnt[less as usize] = less_t;
cnt[more as usize] = more_t;
// 目标
let aim = arr.len() as i32 / 3;
let mut ll = 0;
let mut rr = 0;
while rr < arr.len() as i32 || cnt[more as usize] <= aim {
// cnt[more] 窗口之外,多的数有几个?
if cnt[more as usize] > aim {
// R++ 窗口右边界,右移
cnt[arr[rr as usize] as usize] -= 1;
rr += 1;
} else if cnt[more as usize] < aim {
cnt[arr[ll as usize] as usize] += 1;
ll += 1;
} else {
// 在窗口之外,多的数,够了!
// 少的数,和,另一种数other,能不能平均!都是10个!
if cnt[less as usize] + rr - ll < aim {
cnt[arr[rr as usize] as usize] -= 1;
rr += 1;
} else if cnt[less as usize] + rr - ll > aim {
cnt[arr[ll as usize] as usize] += 1;
ll += 1;
} else {
return true;
}
}
}
return false;
}
// 为了测试
fn random_array(len: i32) -> Vec<i32> {
let mut ans: Vec<i32> = vec![];
for _ in 0..len {
ans.push(rand::thread_rng().gen_range(0, 3));
}
return ans;
}
执行结果如下:

2022-08-24:给定一个长度为3N的数组,其中最多含有0、1、2三种值, 你可以把任何一个连续区间上的数组,全变成0、1、2中的一种, 目的是让0、1、2三种数字的个数都是N。 返回最小的变化次的更多相关文章
- MxDraw云图平台 2022.08.24更新
SDK开发包下载地址: https://www.mxdraw.com/ndetail_30187.html 1. 增加对像扩展数据功能 2. 增加CAD GIS使用功能 https://www.mxd ...
- java—数组乘积输入: 一个长度为n的整数数组input 输出: 一个长度为n的数组result,满足result[i] = input数组中,除了input[i] 之外的所有数的乘积,不用考虑溢出例如 input {2, 3, 4, 5} output: {60, 40, 30, 24}
/** * 小米关于小米笔试题 数组乘积输入: 一个长度为n的整数数组input 输出: 一个长度为n的数组result,满足result[i] = * input数组中,除了input[i] 之外的 ...
- 面试题:给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字
题目:给定一个长度为N的数组,其中每个元素的取值范围都是1到N.判断数组中是否有重复的数字.(原数组不必保留) 方法1.对数组进行排序(快速,堆),然后比较相邻的元素是否相同.时间复杂度为O(nlog ...
- 4.写一个控制台应用程序,接收一个长度大于3的字符串,完成下列功能: 1)输出字符串的长度。 2)输出字符串中第一个出现字母a的位置。 3)在字符串的第3个字符后面插入子串“hello”,输出新字符串。 4)将字符串“hello”替换为“me”,输出新字符串。 5)以字符“m”为分隔符,将字符串分离,并输出分离后的字符串。 */
namespace test4 {/* 4.写一个控制台应用程序,接收一个长度大于3的字符串,完成下列功能: 1)输出字符串的长度. 2)输出字符串中第一个出现字母a的位置. 3)在字符串的第3个字符 ...
- 给定数组a[1,2,3],用a里面的元素来生成一个长度为5的数组,打印出其排列组合
给定数组a[1,2,3],用a里面的元素来生成一个长度为5的数组,打印出其排列组合 ruby代码: def all_possible_arr arr, length = 5 ret = [] leng ...
- hdu3065 病毒侵袭持续中 AC自动机入门题 N(N <= 1000)个长度不大于50的模式串(保证所有的模式串都不相同), 一个长度不大于2000000的待匹配串,求模式串在待匹配串中的出现次数。
/** 题目:hdu3065 病毒侵袭持续中 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065 题意:N(N <= 1000)个长度不大于50的 ...
- C#统计给定的文本中字符出现的次数,使用循环和递归两种方法
前几天看了一个.net程序员面试题目,题目是”统计给定的文本中字符出现的次数,使用循环和递归两种方法“. 下面是我对这个题目的解法: 1.使用循环: /// <summary> /// 使 ...
- hdu6003 Problem Buyer 贪心 给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。
/** 题目:hdu6003 Problem Buyer 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6003 题意:给定n个区间,以及m个数,求从n个区 ...
- C语言:利用指针解决:统计一个长度为2的字符串在另外一个字符串中出现的次数。
//统计一个长度为2的字符串在另外一个字符串中出现的次数. #include <conio.h> #include <stdio.h> #include <string. ...
- 用最小的空间复杂度找出一个长度为n的数组且数据中的元素是[0,n-1]中任一个重复的数据。
用最小的空间复杂度找出一个长度为n的数组且数据中的元素是[0,n-1]中任一个重复的数据. 比如:[1, 2, 3, 3, 2, 2, 6, 7, 8, 9] 中 2 or 3 分析:这道题目,实现比 ...
随机推荐
- Git 小技巧:忽略某些文件的更改
*以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」https://mp.weixin.qq.com/s/dp9Mwq7vf0ASF_FftBN8Ww 作为一枚合格的代码贡献 ...
- Windows命令行备份文件
windows命令行备份文件 0 前言 前段时间,笔者因为在C盘爆满的情况下被windows自动更新了(大概),出现了以下情况: 在试了几种方法后不起作用,无奈下只能重装系统. 在这之前要把之前的一些 ...
- golang中关于死锁的思考与学习
1.Golang中死锁的触发条件 1.1 书上关于死锁的四个必要条件的讲解 发生死锁时,线程永远不能完成,系统资源被阻碍使用,以致于阻止了其他作业开始执行.在讨论处理死锁问题的各种方法之前,我们首先深 ...
- BootstrapBlazor + FreeSql ORM 实战 Table 表格组件维护多表数据 - OneToOne
OneToOne 垂直扩展表字段是很常见的方法, 主表存商品资料, 分表存每个客户对应商品的备注和个性化的价格等等, 本文使用Blazor一步步实现这个简单的需求. 1. 基于实战 10分钟编写数据库 ...
- MyBatis中的#和$有什么区别
什么是MyBatis MyBatis是一款优秀的持久层框架,特别是在国内(国外据说还是 Hibernate 的天下)非常的流行,我们常说的SSM组合中的M指的就是#mybatis#. MyBatis支 ...
- GUI编程--3 Swing
GUI编程-3 Swing 3.1 JFrame 窗口 窗口: package com.ssl.lesson04; import javax.swing.*; import java.awt.*; p ...
- Solon2 接口开发: 分布式 Api Gateway 开发预览
建议使用专业的分布式网关产品,比如: nginx apisix [推荐] k8s ingress controller 等... 对 Solon 来讲,只有 Gateway:它调用本地接口时,则为本地 ...
- 「高频必考」Docker&K8S面试题和答案
先送福利:Go如何自动解压缩包?| 文末送书 Docker 如何在Docker容器内部访问主机上的服务? 可以通过设置主机网络模式,使用--net=host参数来访问主机上的服务.这样,容器和主机将共 ...
- 鼎捷ERP二维码整体解决方案 Tiptop GP条码管理系统 鼎捷ERP移动解决方案 鼎捷条码扫描 鼎捷WMS仓库移动扫码 鼎捷安卓PDA扫码方案 Tiptop 出入库盘点出货条码扫码 提供源码
本人在ERP实施公司做顾问四五年,参与企业实施ERP十多个项目,非常熟悉企业ERP流程,在实施过程遇到众多问题,提出了不少根据企业具体情况的解决方案. 最近定制开发了一套适合企业的条码扫码平台,基于鼎 ...
- [Java EE]辨析: POJO(PO / DTO / VO) | BO/DO | DAO
概念不清,会很影响开发中的逻辑性和条理性,进而影响接口设计,代码编写的质量. 网络上大家对这些个概念的探究很多,但终究没有一个统一的说法. 不论哪家解释,我觉得最重要的是: 1)词汇之间的解释统一: ...