2023-06-20:给定一个长度为N的数组arr,arr[i]表示宝石的价值
你在某天遇到X价值的宝石,
X价值如果是所有剩余宝石价值中的最小值,你会将该宝石送人
X价值如果不是所有剩余宝石价值中的最小值,你会将该宝石放到所有宝石的最后
返回把宝石都送人需要多少天
比如arr = [3,1,4,3,1,2]
在第1天,你遇到了价值3的宝石,但是3并不是所有剩余宝石的价值最小值
所以你把3放在了所有宝石的最后,arr = [1,4,3,1,2,3]
在第2天,你遇到了价值1的宝石,1是所有剩余宝石的价值最小值
所以你把价值1的宝石送人,arr = [4,3,1,2,3]
在第3天,你把价值4的宝石放到最后,arr = [3,1,2,3,4]
在第4天,你把价值3的宝石放到最后,arr = [1,2,3,4,3]
在第5天,你送出了价值1的宝石,arr = [2,3,4,3]
在第6天,你送出了价值2的宝石,arr = [3,4,3]
在第7天,你送出了价值3的宝石,arr = [4,3]
在第8天,你把价值4的宝石放到最后,arr = [3,4]
在第9天,你送出了价值3的宝石,arr = [4]
在第10天,你送出了价值4的宝石,宝石已经没有了。
所以返回10。
1
1
来自TikTok美国笔试。
答案2023-06-20:
1.第一个方法(days1)使用了暴力的方式,通过遍历数组并移动宝石来模拟每一天的操作,直到所有宝石都被送出。时间复杂度较高。
2.第二个方法(days2)使用了更高效的算法。首先构建了一个支持查询累加和和最小值的数据结构(IndexTree和SegmentTree)。然后利用这些数据结构来计算送出所有宝石需要的天数。具体步骤如下:
2.1.初始化累加和数据结构(it)和最小值数据结构(st)。
2.2.设定起始位置(start)为1,找到剩余宝石中的最小值(find)。
2.3.计算从起始位置到最小值之间的宝石总数(daysCount)。
2.4.将最小值送出,更新累加和数据结构(it)和最小值数据结构(st)。
2.5.更新起始位置(start)为最小值。
2.6.重复上述步骤直到所有宝石都被送出。
2.7.返回送出宝石所需的天数。
时间复杂度和空间复杂度如下:
方法1(days1):
- 时间复杂度:,其中N是宝石数组的长度。需要遍历数组N次,并且在每次操作中需要移动宝石,移动的次数也达到了N次。
- 空间复杂度:O(N),需要额外的存储空间来存储宝石数组。
方法2(days2):
- 时间复杂度:,其中N是宝石数组的长度。构建IndexTree和SegmentTree所需的时间复杂度为O(N * logN)。每次查询最小值的时间复杂度为O(logN),总共进行N次查询。因此,总的时间复杂度为。
- 空间复杂度:O(N),需要额外的存储空间来构建IndexTree和SegmentTree。
综上所述,方法1的时间复杂度为,方法2的时间复杂度为。在时间复杂度上,方法2优于方法1。方法1的空间复杂度为O(N),方法2的空间复杂度为O(N)。在空间复杂度上,两种方法相同。
go完整代码如下:
package main
import (
"fmt"
"math"
"math/rand"
"time"
)
// 暴力方法
// 为了验证
func days1(diamonds []int) int {
arr := make([]int, len(diamonds))
copy(arr, diamonds)
ans := 0
for len(arr) > 0 {
ans++
deal(&arr)
}
return ans
}
// 暴力方法
// 为了验证
func deal(arr *[]int) {
head := (*arr)[0]
*arr = (*arr)[1:]
min := head
for _, num := range *arr {
min = int(math.Min(float64(min), float64(num)))
}
if head > min {
*arr = append(*arr, head)
}
}
// 正式方法
// 时间复杂度O(N * (logN)的平方)
func days2(diamonds []int) int {
// n : 位置
n := len(diamonds)
// 1 ~ n : 1
it := NewIndexTree(n)
// 7 6 2...
// 1 2 3....
st := NewSegmentTree(diamonds)
days := 0
find, start := 1, 1
for it.SumRange(1, n) != 0 {
// start ..... find(后续....最小值,最左的位置)
find = findMin(st, start, n)
days += daysCount(it, start, find, n)
// 1
// find
it.Add(find, -1)
st.Update(find, math.MaxInt32)
start = find
}
return days
}
func findMin(st *SegmentTree, start, n int) int {
// start....n 左部分 1 ~ start-1 右
var l, r, min = n, 1, st.Min(1, n)
if st.Min(start, n) == min {
l = start
r = n
} else {
l = 1
r = start - 1
}
var m, ans = -1, -1
for l 0 {
ret += it.tree[i]
i -= i & -i
}
return ret
}
func (it *IndexTree) SumRange(l, r int) int {
return it.Sum(r) - it.Sum(l-1)
}
func (it *IndexTree) Add(i, d int) {
for i > 1
if L mid {
st.update(L, R, C, mid+1, r, rt> 1
ans := math.MaxInt32
if L mid {
ans = int(math.Min(float64(ans), float64(st.minQuery(L, R, mid+1, r, rt
rust完整代码如下:
use std::cmp;
use std::time::SystemTime;
struct IndexTree {
tree: Vec,
n: i64,
}
impl IndexTree {
fn new(size: i64) -> IndexTree {
let tree = vec![0; (size + 1) as usize];
let mut it = IndexTree {
tree: tree,
n: size,
};
for i in 1..=size {
it.add(i, 1);
}
it
}
fn sum(&self, mut i: i64) -> i64 {
let mut ret = 0;
while i > 0 {
ret += self.tree[i as usize];
i -= i & -i;
}
ret
}
fn sum_range(&self, l: i64, r: i64) -> i64 {
self.sum(r) - self.sum(l - 1)
}
fn add(&mut self, mut i: i64, d: i64) {
while i ,
}
impl SegmentTree {
fn new(arr: &[i64]) -> SegmentTree {
let n = arr.len() as i64;
let min = vec![0; ((n + 1) > 1;
if L mid {
self.update_segment(L, R, C, mid + 1, r, rt i64 {
if L > 1;
let mut ans = i64::MAX;
if L mid {
ans = cmp::min(ans, self.min_query(L, R, mid + 1, r, rt i64 {
self.min_query(l, r, 1, self.n, 1)
}
}
fn days1(diamonds: &mut [i64]) -> i64 {
let mut arr = diamonds.to_vec();
let mut ans = 0;
while !arr.is_empty() {
ans += 1;
deal(&mut arr);
}
ans
}
fn deal(arr: &mut Vec) {
let head = arr.remove(0);
let mut min0 = head;
for a in arr.iter() {
min0 = min0.min(*a);
}
if head > min0 {
arr.push(head);
}
}
fn days2(diamonds: &[i64]) -> i64 {
let n = diamonds.len() as i64;
let mut it = IndexTree::new(n);
let mut st = SegmentTree::new(diamonds);
let mut days = 0;
let mut find = 1;
let mut start = 1;
while it.sum_range(1, n) != 0 {
find = find_min(&st, start, n);
days += days_count(&it, start, find, n);
it.add(find, -1);
st.update(find, i64::MAX);
start = find;
}
days
}
fn find_min(st: &SegmentTree, start: i64, n: i64) -> i64 {
let (mut l, mut r, mut min) = (n, 1, st.min(1, n));
if st.min(start, n) == min {
l = start;
r = n;
} else {
l = 1;
r = start - 1;
}
let (mut m, mut ans) = (-1, -1);
while l > 1;
if st.min(l, m) == min {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
ans
}
fn days_count(it: &IndexTree, start: i64, find: i64, n: i64) -> i64 {
if start Vec {
let mut arr = vec![0; n as usize];
for i in 0..n {
arr[i as usize] = ((rand::random::() % v) + v) % v;
}
arr
}
fn main() {
let now = SystemTime::now();
println!("例子测试开始");
let arr = vec![3, 1, 4, 3, 1, 2];
println!("{}", days1(&mut arr.to_vec()));
println!("{}", days2(&arr));
println!("例子测试结束");
let n = 100;
let v = 100000;
let test_times = 1000;
println!("随机测试开始");
for _ in 0..test_times {
let n = ((rand::random::() % n) + n) % n + 1;
let diamonds = random_array(n, v);
let ans1 = days1(&mut diamonds.clone());
let ans2 = days2(&diamonds);
if ans1 != ans2 {
println!("出错了!");
}
}
println!("随机测试结束");
println!("性能测试开始");
let n = 100000;
let v = 1000000000;
let diamonds = random_array(n, v);
println!("宝石数量 : {}", n);
println!("价值范围 : {}", v);
let start = SystemTime::now();
days2(&diamonds);
let end = SystemTime::now();
println!(
"运行时间 : {} 毫秒",
end.duration_since(start).unwrap().as_millis()
);
println!("性能测试结束");
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: Docker安装MS SQL Server并使用Navicat远程连接
MS SQL Server简介 Microsoft SQL Server(简称SQL Server)是由微软公司开发的关系数据库管理系统,它是一个功能强大、性能卓越的企业级数据库平台,用于存储和处理大型数据集、支持高效查询和分析等操作。SQL Server…