码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 累加出整个范围所有的数最少还需要几个数


    累加出整个范围所有的数最少还需要几个数

    作者:Grey

    原文地址:

    博客园:累加出整个范围所有的数最少还需要几个数

    CSDN:累加出整个范围所有的数最少还需要几个数

    题目描述#

    给定一个有序的正数数组 arr 和一个正数 aim ,如果可以自由选择 arr 中的数字,想累加得到 1~aim 范围上所有的数,返回 arr 最少还缺几个数。

    例如:

    arr = {1,2,3,7},aim = 15

    想累加得到1~15范围上所有的数,arr 还缺 14 这个数,所以返回 1。

    arr = {1,5,7},aim = 15

    想累加得到1~15范围上所有的数,arr 还缺 2 和 4,所以返回 2。

    题目链接见:累加出整个范围所有的数最少还需要几个数

    主要思路#

    如果区间是1~1,可以组成的数是1;

    如果区间是1~2,可以组成的数是1,2,3,即1~3。

    如果区间是1~3,可以组成的数是1,2,3,4,5,即1~5。

    ……

    依此类推

    如果区间是1~n,可以组成的数是1,2……(2*n - 2),(2*n - 1),即1~(2*n - 1)。

    所以,如果数组已经可以组成1~range,但是还没有达到1~aim,数组需要增加一个数range+1,就可以让数组的可以组成范围扩大到2*range+1,不断这个过程,直到覆盖1~aim这个区间,这种做法是最经济的。

    完整代码如下

    import java.util.Arrays;
    import java.util.Scanner;
    
    /**
     * @author Young
     * @version 1.0
     * @date 2021/1/25 0:06
     */
    public class Main {
        public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
            int aim = in.nextInt();
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = in.nextInt();
            }
            System.out.println(missing(arr, aim));
            in.close();
        }
    
        // 如果要实现1~range所有目标,但整个目标还没有达到1~aim,你永远缺range+1,一定是最省且最经济的,补上range+1后,能达到的数是1~2*range+1
        // 先将数组排序,依次考察如何最经济使用i位置的数
        public static int missing(int[] arr, int aim) {
            int miss = 0;
            long range = 0;
            Arrays.sort(arr);
            for (int item : arr) {
                while (item > range + 1) {
                    // 数组每次可以扩充的范围
                    range += (range + 1);
                    miss++;
                    if (range >= aim) {
                        return miss;
                    }
                }
                range += item;
                if (range >= aim) {
                    return miss;
                }
            }
            while (aim >= range + 1) {
                range += range + 1;
                miss++;
            }
            return miss;
        }
    }
    
    

    代码说明

    首先对数组进行排序的目的是找到连续的数组区间,这样才能判断扩散的范围,然后遍历数组,其中

                while (item > range + 1) {
                    // 数组每次可以扩充的范围
                    range += (range + 1);
                    miss++;
                    if (range >= aim) {
                        return miss;
                    }
                }
    

    表示数组出现了断层,比如 item 之前的数可以组成的1~8,但是 item 值为 12,说明9~11无法被组成,此时,原数组需要补充一个 9(即:miss++),就可以将原数组的可组成范围扩大到1~17(即:range+=(range+1))。

    时间复杂度O(N*logN),瓶颈主要是前面的排序的时间复杂度。

    空间复杂度O(1)。

    更多#

    算法和数据结构笔记

  • 相关阅读:
    Spring5学习笔记03--Bean的生命周期
    mysql【力扣】
    Linux入门之 init
    算法通过村第十四关-堆|青铜笔记|堆结构
    模型实战(16)之StrongSort (OSNET)配合YOLOv5、v7、v8 实现多目标跟踪详解
    Java8 巨强大的新特性 lambda表达式
    怎样用 Python数据 写一个自动交易的股票程序接口?
    vue3中使用vue3-pdf-app和使用浏览器内置的PDF插件浏览器PDF文件
    Shopify主题二次开发必备技能:全面指南和最佳实践
    springcloud旅游网站源码
  • 原文地址:https://www.cnblogs.com/greyzeng/p/16725698.html
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号