【备战秋招】每日一题:4月29日美团春招第三题:题面+题目思路 + C++/python/js/Go/java带注释

news2024/11/17 15:47:09

为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第三题-酒王

在线评测链接:P1268

题目内容

塔子哥和他的朋友们共 n 人是一群热爱生活的年轻人,他们经常在一起吃饭,聊天,玩游戏。有一天,他们决定去一家新开的酒吧,品尝各种美酒。但是他们发现,酒吧的老板是一个很奇怪的人,他给他们出了一个挑战:如果他们能在一个小时内喝完所有的酒,就可以免单;如果有人中途放弃,就要付双倍的钱。塔子哥和他的朋友们觉得这是一个很有趣的游戏,于是接受了挑战。

为了增加难度和乐趣,他们决定用一个特殊的方式来喝酒。他们顺时针围成一圈,假设标号为 1 到 n 。从 1 号开始,每次从当前的人顺时针数 k 个,然后这个人喝一杯酒。第 i 个人的酒量为a_i意味着当他喝了a_i杯酒后将因无法忍受而离席。现在他们请你依次输出离席的人的编号,以此来判断谁是酒王。

输入描述

输入第一行为两个正整数 n,k 。

输入第二行为 n 个正整数,第 i 个数为 a_i

对于所有的数据: 1\le n\le 1000,1\le k\le 10^9,1\le a_i \le 10000,n\times \sum a_i\le 10^7

输出描述

输出一行输出用空格隔开的 n 个正整数,表示按时间从早到晚离席的人的编号。

样例

输入

5 4
1 1 7 9 8

输出

1 5 2 4 3

思路

约瑟夫环问题+贪心

本题是经典的约瑟夫环问题变种。

从当前位置 cur 开始喝酒,下一个位置为顺时针的 cur + k 这个位置。由于这是一个圆,故一定会在一些人之间循环喝酒,一部分人在这段时间总是不会喝酒,我们称当前的情况为当前的酒局。喝酒的这部分人中,直到存在一个人喝完酒后,剩余酒杯数为 0 ,这一部分人的喝酒结束,整个酒局将被修改。

我们需要考虑,当前的喝酒的人中,从当前位置 cur 开始,一直顺时针 k次找下一个人,而离席的第一个人,必然是酒杯数最少的。

由于存在先后关系,从 cur 开始顺时针 k 次找下一个喝酒的人,这些人中,剩余酒杯数最少,且是所有剩余酒杯数最少的人中第一个喝酒的人,是第一个离席的人。这个人前面的人会和他和一样多的酒,后面的人会比他少喝一杯酒。

这个人离席后,其顺时针后面的人就接上其位置,进行下一次的酒局。

时间复杂度:O(n^2)

视频实况 v1, 21:12-65:56

类似题目推荐

LeetCode

剑指 Offer 62. 圆圈中最后剩下的数字

CodeFun2000

P1118 2023.03.26-阿里春招-第二题-报数字

代码

CPP

#include <bits/stdc++.h>
using namespace std;
​
const int N = 1010;
pair<int, int> a[N];
int ans[N], g;
int vis[N];
int people[N];
int n, k;
​
int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; ++i) scanf("%d", &a[i].first), a[i].second = i + 1;
​
    int cur = 0;
    while (n > 0) {
        for (int i = 0; i < n; ++i) vis[i] = 0;
        int cnt = 0;
        int minv = 0x3f3f3f3f;
​
        // 找到当前回合所有可能需要喝酒的人
        while (!vis[cur]) {
            people[cnt++] = cur;
            vis[cur] = 1;
            minv = min(minv, a[cur].first);
            cur = (cur + k) % n;
        }
​
        // 我们找到从 cur 开始的最小值
        // cur 之前的人要减去 minv
        // cur 之后的人要减去 minv - 1
        for (int i = 0; i < cnt; ++i)
            if (minv == a[people[i]].first) {
                for (int j = 0; j < i; ++j) a[people[j]].first -= minv;
                for (int j = i + 1; j < cnt; ++j) a[people[j]].first -= minv - 1;
​
                //  将其排列好,然后再往后走 k 个
                int pos = people[i];
                ans[++g] = a[pos].second;
                for (int j = pos + 1; j < n; ++j) a[j - 1] = a[j];
​
                if (n > 1) {
                    // 走 k - 1步是因为下一个人继承了当前离席的人的位置,故从当前离席的顺时针走 k 个
                    cur = (pos + k - 1) % (n - 1);
                }
​
                break;
            }
​
        n -= 1;
    }
​
    for (int i = 1; i <= g; ++i) printf("%d%c", ans[i], " \n"[i == g]);
​
    return 0;
}

python

N = 1010
​
n, k = map(int, input().split())
​
a = [[0, 0] for i in range(N)]
vis = [0] * N
​
line = input().split()
for i in range(len(line)):
    a[i] = ([int(line[i]), i + 1])
​
cur = 0
ans = []
while n > 0:
    for i in range(n):
        vis[i] = 0
​
    people = []
    minv = 0x3f3f3f3f
    # 找到当前回合所有可能需要喝酒的人
    while vis[cur] == 0:
        people.append(cur)
        vis[cur] = 1
        minv = min(minv, a[cur][0])
        cur = (cur + k) % n
    
    # 我们找到从 cur 开始的最小值
    # cur 之前的人要减去 minv
    # cur 之后的人要减去 minv - 1
    for i in range(len(people)):
        if minv == a[people[i]][0]:
            for j in range(i):
                a[people[j]][0] -= minv
            for j in range(i + 1, len(people)):
                a[people[j]][0] -= minv - 1
​
            # 将其排列好,然后再往后走 k 个
            pos = people[i]
            ans.append(a[pos][1])
            a.pop(pos)
​
            if n > 1:
                # 走 k - 1步是因为下一个人继承了当前离席的人的位置,故从当前离席的顺时针走 k 个
                cur = (pos + k - 1) % (n - 1)
​
            break
    n -= 1
    
for i in ans:
    print(i, end=' ')
print()

Java

import java.util.Arrays;
import java.util.Scanner;
​
public class Main {
    static final int N = 1010;
    static int[] ans = new int[N], people = new int[N];
    static int[] vis = new int[N];
    static int[][] a = new int[N][2];
​
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        for (int i = 0; i < n; ++i) {
            a[i][0] = sc.nextInt();
            a[i][1] = i + 1;
        }
​
        int g = 0;
        int cur = 0;
        while (n > 0) {
            for (int i = 0; i < n; ++i) vis[i] = 0;
            int cnt = 0;
            int minv = 0x3f3f3f3f;
            // 找到当前回合所有可能需要喝酒的人
            while (vis[cur] == 0) {
                people[cnt++] = cur;
                vis[cur] = 1;
                minv = Math.min(minv, a[cur][0]);
                cur = (cur + k) % n;
            }
​
            // 我们找到从 cur 开始的最小值
            // cur 之前的人要减去 minv
            // cur 之后的人要减去 minv - 1  
            for (int i = 0; i < cnt; ++i) {
                if (minv == a[people[i]][0]) {
                    for (int j = 0; j < i; ++j) {
                        a[people[j]][0] -= minv;
                    }
                    for (int j = i + 1; j < cnt; ++j) {
                        if (j != i) {
                            a[people[j]][0] -= minv - 1;
                        }
                    }
                    
                    // 将其排列好,然后再往后走 k 个
                    int pos = people[i];
                    ans[++g] = a[pos][1];
                    for (int j = pos + 1; j < n; ++j) {
                        a[j - 1] = a[j];
                    }
​
                    // 走 k - 1步是因为下一个人继承了当前离席的人的位置,故从当前离席的顺时针走 k 个
                    if (n > 1) {
                        cur = (pos + k - 1) % (n - 1);
                    }
​
                    break;
                }
            }
            n -= 1;
        }
​
        for (int i = 1; i <= g; ++i) {
            System.out.print(ans[i] + " ");
        }
        System.out.println();
    }
}

Go

package main
​
import "fmt"
​
type Pair struct {
    first, second int
}
​
const N = 1010
​
var a [N]Pair
var ans [N]int
var vis [N]bool
var people [N]int
var g int
var n, k int
​
func main() {
    fmt.Scan(&n, &k)
    for i := 0; i < n; i++ {
        fmt.Scan(&a[i].first)
        a[i].second = i + 1
    }
​
    cur := 0
    for n > 0 {
        for i := 0; i < n; i++ {
            vis[i] = false
        }
        cnt := 0
        minv := 0x3f3f3f3f
​
        // 找到当前回合所有可能需要喝酒的人
        for !vis[cur] {
            people[cnt] = cur
            vis[cur] = true
            minv = min(minv, a[cur].first)
            cur = (cur + k) % n
            cnt++
        }
​
        // 我们找到从 cur 开始的最小值
        // cur 之前的人要减去 minv
        // cur 之后的人要减去 minv - 1
        for i := 0; i < cnt; i++ {
            if minv == a[people[i]].first {
                for j := 0; j < i; j++ {
                    a[people[j]].first -= minv
                }
                for j := i + 1; j < cnt; j++ {
                    a[people[j]].first -= minv - 1
                }
​
                //  将其排列好,然后再往后走 k 个
                pos := people[i]
                ans[g+1] = a[pos].second
                g++
                for j := pos + 1; j < n; j++ {
                    a[j-1] = a[j]
                }
​
                if n > 1 {
                    // 走 k - 1步是因为下一个人继承了当前离席的人的位置,故从当前离席的顺时针走 k 个
                    cur = (pos + k - 1) % (n - 1)
                }
​
                break
            }
        }
​
        n--
    }
​
    for i := 1; i <= g; i++ {
        if i == g {
            fmt.Printf("%d\n", ans[i])
        } else {
            fmt.Printf("%d ", ans[i])
        }
    }
}
​
func min(x, y int) int {
    if x < y {
        return x
    }
    return y
}

Js

process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
    input += data;
    return;
});
process.stdin.on('end', () => {
    const lines = input.trim().split('\n');
    [n, k] = lines[0].split(' ').map(Number);
    const a = lines[1].split(' ').map((x, i) => [Number(x), i + 1]);
    const people = new Array(n);
    const ans = new Array(n);
​
    let cur = 0;
    let g = 0;
    while (n > 0) {
        const vis = new Array(n).fill(false);
        let cnt = 0;
        let minv = Infinity;
​
        // 找到当前回合所有可能需要喝酒的人
        while (!vis[cur]) {
            people[cnt++] = cur;
            vis[cur] = true;
            minv = Math.min(minv, a[cur][0]);
            cur = (cur + k) % n;
        }
​
        // 我们找到从 cur 开始的最小值
        // cur 之前的人要减去 minv
        // cur 之后的人要减去 minv - 1
        for (let i = 0; i < cnt; i++) {
            const p = people[i];
            if (minv === a[p][0]) {
                for (let j = 0; j < i; j++) {
                    a[people[j]][0] -= minv;
                }
                for (let j = i + 1; j < cnt; j++) {
                    a[people[j]][0] -= minv - 1;
                }
​
                // 将其排列好,然后再往后走 k 个
                const pos = p;
                ans[g++] = a[pos][1];
                for (let j = pos + 1; j < n; j++) {
                    a[j - 1] = a[j];
                }
​
                if (n > 1) {
                    // 走 k - 1 步是因为下一个人继承了当前离席的人的位置,故从当前离席的顺时针走 k 个
                    cur = (pos + k - 1) % (n - 1);
                }
​
                break;
            }
        }
​
        n--;
    }
​
    console.log(ans.join(' '));
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/654945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

预设Preset简单使用

作用 是一个资源文件。可以保存组件、资源、项目设置的属性&#xff0c;将属性应用到组件、资源、项目设置上。 例如&#xff0c;创建一个Transform预设&#xff0c;可记录Transform的属性&#xff0c;其他Transform应用预设&#xff0c;会使用预设中的数据。 文档 预设 预设…

【Vue全家桶高仿小米商城】——(二)Git安装与配置

文章目录 第二章&#xff1a;Git安装和配置一、Windows/Mac/Linux安装二、环境变量配置、开发工具配置Windows - 环境变量Mac/Linux - 环境变量VSCode配置Git使用 VScode git&#xff0c;提交到仓库 三、存储密码 - SSH添加秘钥Git配置命令遇到的问题 四、Git常用命令 第二章&…

新手怎么注册速卖通及其流程?图文详解版不信你还不会!

龙哥发现最近讨论速卖通的人还挺多的&#xff0c;今天龙哥就给大家讲一下新手注册速卖通的流程&#xff0c;特别是需要你提前准备好的资料。感兴趣的朋友接着往下看吧&#xff01; 速卖通店铺注册条件 1、营业执照、商标 速卖通要求注册商家必须具备合法的企业身份或个体工商户…

浅谈职场中的工作失误

浅谈职场中的工作失误 关于职场中的工作失误如何处理失误一点感言 笔者在一家软件公司从事传统的数据运维工作&#xff0c;也有十年之久了。十年的数据运维工作&#xff0c;真是一步一个脚印&#xff0c;一步一个坑踩出来的&#xff0c;也没想到这一干就是十年… 关于职场中的…

SeqTrack: Sequence to Sequence Learning for Visual Object Tracking

摘要 在本文中&#xff0c;我们提出了一种新的序列到序列学习框架的视觉跟踪&#xff0c;称为SeqTrack。它将视觉跟踪转换为一个序列生成问题&#xff0c;它以自回归的方式预测对象边界盒。这与之前的Siamese跟踪器和transformer跟踪器不同&#xff0c;它们依赖于设计复杂的磁…

【活动访谈】发力数字基座 推动物联创新—航天科技控股集团AIRIOT4.0平台发布会活动专访

近日&#xff0c;由航天科技控股集团股份有限公司主办的“数字基座 智慧物联—AIRIOT4.0平台发布会”在北京圆满落幕。航天三院科技委总工程师王连宝应邀出席本次会议并接受媒体采访&#xff0c;共同参与访谈的还有AIRIOT产品研发创始人、航天科技控股集团股份有限公司智慧物联…

python生成日报

目录 一&#xff1a;日报生成工具二&#xff1a;日报工具使用方式三&#xff1a;最终日报生成展示 一&#xff1a;日报生成工具 #!/usr/bin/python # coding:utf8class GetHtml(object):def __init__(self):self._html_head """<html><body style&qu…

美颜滤镜SDK在实时视频应用中的应用

随着智能手机的普及和网络带宽的增强&#xff0c;实时视频应用已经成为了人们日常生活中不可或缺的一部分。而在实时视频应用中&#xff0c;美颜滤镜SDK的应用也越来越广泛。本文将介绍美颜滤镜SDK在实时视频应用中的应用。 一、美颜滤镜SDK的概念 美颜滤镜SDK是一种软件开发工…

Jetpack Compose — 让Composable具备生命周期感知

Jetpack Compose — 让Composable具备生命周期感知 我们将研究不同的方法来实现可组合&#xff08;Composable&#xff09;的生命周期感知。我们还将了解可组合生命周期和视图&#xff08;View&#xff09;生命周期之间的区别。 我们将逐步探索不同的解决方案&#xff0c;以寻…

C51/C52单片机,最小系统

一个小白&#xff0c;开始学习单片机&#xff0c;从C51/52开始&#xff0c; 我学习的型号是STC98C52单片机。 STC89C52是一种低功耗、高性能CMOS8位微控制器&#xff0c;具有8K在系统可编程Flash存储器。在单芯片上&#xff0c;拥有灵巧的8位CPU和在系统可编程Flash&#xff0…

NeRF系列(4):Ha-NeRF: Hallucinated Neural Radiance Fields in the Wild论文解读

主页&#xff1a; 主页&#xff1a;Ha-NeRF&#x1f606;: Hallucinated Neural Radiance Fields in the Wildhttps://rover-xingyu.github.io/Ha-NeRF/论文&#xff1a;https://openaccess.thecvf.com/content/CVPR2022/papers/Chen_Hallucinated_Neural_Radiance_Fields_in_…

常用API(Object,Objects,StringBuilder,Math,System,BigDecimal)

1&#xff1a;Object类 1&#xff1a;Object类的作用&#xff1a; 一个类要么默认继承Object类&#xff0c;要么间接继承了Object类&#xff0c;Object类是Java中的祖宗类。Object类的方法是一切子类都可以直接使用的&#xff0c;所以我们要学习Object类的方法。 2&#xff…

容器(第八篇)ansible-模块

ansible是什么&#xff1f; Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。 Ansible能批量配置、部署、…

直线方程y=kx+b 已知两点a,b。求ab中间任一点坐标x,y

参考文章 斜率怎么求 已知斜率及另一点坐标,求另一点坐标方法 三角形斜率 DirectX C 3D编程基础 5 [三角形光栅化] 自制中字 直线方程公式ykxb k斜率&#xff0c;b截距 已知点a&#xff08;1,2&#xff09; b&#xff08;4,3&#xff09;绿色线段 求斜率k(by-ay)/(bx-ax)或(a…

idea运行main方法或Test避免编译整个应用的方法

已建项目中修改 Main函数不biuld : 光标点到main函数里&#xff0c;右键->Modify Run COnfigurations->Modify options Test 不build 或者单独在每个test里 右键-Modify Run COnfigurations->移除build 对于新建工程统一修改配置: File->New Project Setting…

Java30天拿下---第一天(JDK,JRE,JVM,转义字符,注释,代码规范,数据类型)

Java开发&#xff08;30天拿下---第一天&#xff09; 一 hello world以及JDK,JRE,JVM二 转义字符三 注释四 代码规范五 DOS命令&#xff08;了解&#xff09;六 变量1.加号的使用2.数据类型整型浮点型字符类型布尔类型自动类型转换强制类型转换String类型 七 API文档 一 hello …

【备战秋招】每日一题:5月13日美团春招第一题:题面+题目思路 + C++/python/js/Go/java带注释

为了更好的阅读体检&#xff0c;为了更好的阅读体检&#xff0c;&#xff0c;可以查看我的算法学习博客第一题-塔子哥的数字 在线评测链接:P1286 题目描述 塔子哥是一个数学爱好者&#xff0c;他经常思考各种数字之间的奥秘。今天&#xff0c;他想要解决一个有趣的问题&…

业务流程自动化:ThinkAutomation Professional Crack

ThinkAutomation 助力您的业务流程自动化。自动执行本地和基于云的业务流程&#xff0c;以降低成本并节省时间。 自动化传入的通信渠道&#xff0c;监控数据库&#xff0c;对传入的Webhook&#xff0c;Web表单和聊天机器人做出反应。处理文档、附件、本地文件和其他邮件源。 …

TOGAF10®标准中文版(全文目录)

The Open Group是一个通过技术标准实现业务目标的全球联盟。我们拥有超过870个成员组织&#xff0c;成员来自技术社区的各个部门&#xff0c;包括客户、系统和解决方案供应商、工具供应商、集成商和顾问&#xff0c;以及学者和研究人员。 The Open Group的使命是通过以下方式…

33、js - 面试 - 事件循环 微任务 宏任务

1、事件循环♻️&#xff08;EventLoop&#xff09; js是单线程语言&#xff0c;也就是某一刻只能执行一行代码&#xff0c;为了让耗时代码不阻塞其他代码运行&#xff0c;设计了事件循环模型。 事件循环是一个并发模型&#xff0c;负责执行代码、收集异步任务的模型&#xff0…