2023-03-02:给定一个数组arr,长度为n,
任意相邻的两个数里面至少要有一个被选出来,组成子序列,才是合法的!
求所有可能的合法子序列中,最大中位数是多少?
中位数的定义为上中位数,
[1, 2, 3, 4]的上中位数是2,
[1, 2, 3, 4, 5]的上中位数是3,
2 <= n <= 10^5,
1 <= arr[i] <= 10^9。
来自京东。实习岗位笔试题。

答案2023-03-02:

这道题看起来是实习题,实际上有难度。
方法一:要i还是不要i,递归或者动态规划。
方法二:以结果为导向,二分法。
时间复杂度:O(N*logN)。
空间复杂度:O(N)。

代码用rust编写。代码如下:

use rand::Rng;
use std::collections::HashMap;
use std::iter::repeat;
fn main() {
let nn = 20;
let vv = 1000;
let test_times = 5000;
println!("测试开始");
for i in 0..test_times {
let n = rand::thread_rng().gen_range(0, nn) + 1;
let mut arr = random_array(n, vv);
let ans1 = best_median1(&mut arr);
let ans2 = best_median2(&mut arr);
if ans1 != ans2 {
println!("出错了!");
return;
}
}
println!("测试结束");
} fn valid_sub_max_sum(arr: &mut Vec<i32>) -> i32 {
return zuo(arr, 0, 1);
} // 当前来到i位置
// 如果arr[i-1]位置的数选了,pre == 1
// 如果arr[i-1]位置的数没选,pre == 0
// arr[i....]最大合法子序列的累加和是多少
fn zuo(arr: &mut Vec<i32>, i: i32, pre: i32) -> i32 {
if i == arr.len() as i32 {
return 0;
}
// 还有数!
// 可能性1 : 不要i位置的数
let mut p1 = i32::MIN;
if pre == 1 {
p1 = zuo(arr, i + 1, 0);
}
// 可能性2 : 要i位置的数
let mut p2 = i32::MIN;
let mut next2 = zuo(arr, i + 1, 1);
if next2 != i32::MIN {
p2 = arr[i as usize] + next2;
}
return if p1 > p2 { p1 } else { p2 };
} // 启发函数
// 如果数组中的值只有1和-1,
// 你可以从左往右选择数字组成子序列,
// 但是要求任何两个相邻的数,至少要选1个
// 请返回子序列的最大累加和
// arr : 数组
// i : 当前来到i位置
// pre : 前一个数字(i-1位置),当初选了没有
// 如果pre == 0, 表示i-1位置的数字,当初没有选
// 如果pre == 1, 表示i-1位置的数字,当初选了
// 返回arr[i...]的子序列,最大累加和
fn max_sum(arr: &mut Vec<i32>, i: i32, pre: i32) -> i32 {
if i == arr.len() as i32 {
return 0;
}
// 可能性1 : 就是要选当前i位置的数
let mut p1 = arr[i as usize] + max_sum(arr, i + 1, 1);
// 可能性1 : 就是不选当前i位置的数
let mut p2 = -1;
if pre == 1 {
// 只有前一个数字选了,当前才能不选
p2 = max_sum(arr, i + 1, 0);
}
return if p1 > p2 { p1 } else { p2 };
} // 暴力方法
// 为了验证
fn best_median1(arr: &mut Vec<i32>) -> i32 {
let mut path: Vec<i32> = repeat(0).take(arr.len()).collect();
return process(arr, 0, true, &mut path, 0);
} fn process(arr: &mut Vec<i32>, i: i32, pre: bool, path: &mut Vec<i32>, size: i32) -> i32 {
if i == arr.len() as i32 {
if size == 0 {
return 0;
}
let mut sort: Vec<i32> = repeat(0).take(size as usize).collect();
for j in 0..size {
sort[j as usize] = path[j as usize];
}
sort.sort();
return sort[(sort.len() - 1) / 2];
} else {
path[size as usize] = arr[i as usize];
let mut ans = process(arr, i + 1, true, path, size + 1);
if pre {
ans = get_max(ans, process(arr, i + 1, false, path, size));
}
return ans;
}
} fn get_max<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
} // 正式方法
// 时间复杂度O(N*logN)
fn best_median2(arr: &mut Vec<i32>) -> i32 {
let n = arr.len() as i32;
let mut sort: Vec<i32> = repeat(0).take(n as usize).collect();
for i in 0..n {
sort[i as usize] = arr[i as usize];
}
sort.sort();
// int[] arr = { 5, 3, 6, 2, 9, 7 };
// int[] sort = { 2, 3, 5, 6, 7, 9 };
// 0 1 2 3 4 5
// l r
let mut l = 0;
let mut r = n - 1;
let mut m = 0;
let mut ans = -1;
let mut help: Vec<i32> = repeat(0).take(n as usize).collect();
let mut dp: Vec<Vec<i32>> = repeat(repeat(0).take(2).collect())
.take((n + 1) as usize)
.collect();
while l <= r {
m = (l + r) / 2;
if max_sum1(arr, &mut help, &mut dp, sort[m as usize], n) > 0 {
ans = sort[m as usize];
l = m + 1;
} else {
r = m - 1;
}
}
return ans;
} // 如果中位数定成median,
// 如果任意相邻的两数,至少选一个,来生成序列
// 所有这样的序列中,
// 到底有没有一个序列,其中>= median的数字,能达到一半以上
fn max_sum1(
arr: &mut Vec<i32>,
help: &mut Vec<i32>,
dp: &mut Vec<Vec<i32>>,
median: i32,
n: i32,
) -> i32 {
for i in 0..n {
help[i as usize] = if arr[i as usize] >= median { 1 } else { -1 };
}
let mut i = n - 1;
while i >= 0 {
dp[i as usize][0] = help[i as usize] + dp[(i + 1) as usize][1];
dp[i as usize][1] = get_max(
help[i as usize] + dp[(i + 1) as usize][1],
dp[(i + 1) as usize][0],
);
i -= 1;
}
return dp[0][1];
} // 为了测试
fn random_array(n: i32, v: i32) -> Vec<i32> {
let mut ans: Vec<i32> = repeat(0).take(n as usize).collect();
for i in 0..n {
ans[i as usize] = rand::thread_rng().gen_range(0, v);
}
return ans;
}

2023-03-02:给定一个数组arr,长度为n, 任意相邻的两个数里面至少要有一个被选出来,组成子序列,才是合法的! 求所有可能的合法子序列中,最大中位数是多少? 中位数的定义为上中位数, [1,的更多相关文章

  1. delphi 判断一个数组的长度用 Length 还是 SizeOf ?

    判断一个数组的长度用 Length 还是 SizeOf ?最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适! 如果是一维数组.且元素大小是 ...

  2. 有两个数a,b,请写一个函数交换a,b

    题目:有两个数a,b,请写一个函数交换a,b,具体实现如下: #include<stdlib.h> #include<stdio.h> int swap(int * pA, i ...

  3. 算法题——给定一个数组 arr,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

    参考自:https://blog.csdn.net/qq_38200548/article/details/80688630 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] ...

  4. java 一个数组的长度

    package java03; /* *如何获取数组长度 : * 格式: * 数组名称.length * * 这会得到一个int数字,代表数组的长度 * * 数组一旦创建,程序运行期间,长度不可改变 ...

  5. 牛客网2016.4.11(两个数相加为sum/计数一个int型的二进制有多少个1/二叉树是否左右对称)

    求最小的两个数相加为sum //求最小的两个数相加为sum public ArrayList<Integer> FindNumbersWithSum(int [] array,int su ...

  6. 判断一个数组的长度用 Length 还是 SizeOf ?

    最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适! 如果是一维数组.且元素大小是一个字节, 这样用看不出错误, 譬如: var   arr ...

  7. C语言之实现函数返回一个数组,以及选择排序,还有折半查找。这是同学的一个作业。。。

    作业的具体要求如下: 编写一个完整的程序,实现如下功能.(1)    输入10个无序的整数.(2)    用选择排序法将以上接收的10个无序整数按从大到小的顺序排序.(3)    要求任意输入一个整数 ...

  8. [java大数据面试] 2018年4月百度面试经过+三面算法题:给定一个数组,求和为定值的所有组合.

    给定一个数组,求和为定值的所有组合, 这道算法题在leetcode应该算是中等偏下难度, 对三到五年工作经验主要做业务开发的同学来说, 一般较难的也就是这种程度了. 简述经过: 不算hr面,总计四面, ...

  9. 位运算解决“一个数组中,只有一个数字出现n次,其他数字出现k次”问题

    转自:https://blog.csdn.net/monster_girl/article/details/52928864 在学习完位操作后,经常会遇到一类关于查找缺失整数的问题. 第一类是给你一个 ...

  10. js算法之把一个数组按照指定的数组大小分割成若干个数组块

    题目描述:     把一个数组arr按照指定的数组大小size分割成若干个数组块. 例如:   chunk([1,2,3,4],2)=[[1,2],[3,4]];   chunk([1,2,3,4,5 ...

随机推荐

  1. git提交的时候,报错yarn run v1.21.1 ,SyntaxError: Cannot use import statement outside a module 解决

    原因是 lint-staged这个依赖中,需要的node的版本是, 而我使用的node版本是12.13.1 ,切换成14.17.0就可以了

  2. swagger 增强UI --knife4j

    knife4j 文档:  https://gitee.com/xiaoym/knife4j (1)简介 knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是sw ...

  3. Nginx如何升级Openssl

    1. 什么是Openssl? 在计算机网络上,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连线者的身份.这个包广泛被应用在互联网的网页服务器 ...

  4. DVWA-Command Injection(命令执行)

    命令执行漏洞,顾名思义,服务端在进行一些网站的操作.管理的时候,需要调用系统命令,如果对传入的命令参数没有进行一些过滤,可以直接执行服务器系统的命令终端 LOW 审计源码 <?php // 判断 ...

  5. Less-7 '))闭合 和 secure_file_priv 配置写入一句话木马

    Less-7使用的文件导出select ... into outfile ....,一个文件上传. mysql安全配置里有一个配置secure_file_priv控制文件的导出导入. secure_f ...

  6. Python查找存储区0KB文件并记录下地址

    查找存储区域中0KB大小文件,可以根据需要变更指定大小. #-*- coding: utf-8 -*- #!/usr/bin/python from os.path import isdir,absp ...

  7. 王树森Transformer学习笔记

    目录 Transformer Attention结构 Self-Attention结构 Multi-head Self-Attention BERT:Bidirectional Encoder Rep ...

  8. Hugging Face 社区中蓬勃发展的计算机视觉

    在 Hugging Face 上,我们为与社区一起推动人工智能领域的民主化而感到自豪.作为这个使命的一部分,我们从去年开始专注于计算机视觉.开始只是 Transformers 中 Vision Tra ...

  9. ACM-学习记录-DP-1

    DPL_1_A: Coin Changing Problem 每次均有两种选择,即选择当前的,即为在当前状态+1,否则维持原来的T[j+d[i]] #include<iostream> # ...

  10. Kubeadm安装k8s集群升级100年证书时报错:Unable to connect to the server: EOF:求解决方法.

    报错信息: 使用命令时: Kubelet服务报错: 报错情况,在更新完k8s100年证书的时候,到最后重新启动kubelet服务的时候,服务是可以重新启动的,但是kubectl的命令是无法使用的,会等 ...