IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 大厂算法反复面试-最长递增子序列 -> 正文阅读

[数据结构与算法]大厂算法反复面试-最长递增子序列

题目

有n个动物重量分别a1,a2,a3…an,

这群动物一起玩叠罗汉游戏

规定从左往右选择动物,每只动物左边动物的总重量不超过自己的重量

返回最多能选多少个动物,求一个高效的算法

比如有7个动物,从左往右重量依次为 1,3,5,7,9,11,21

最多能选5个动物 1,3,5,9,21

注意:

  • 实际给定的数组可能是无序的
  • 要求从左往右选动物,且不能打乱原始数组

分析

这道题应该怎么做呢?

确定你审清楚了题目意思,这点很重要,不然浪费了磨脑壳,朝着错误的方向努力,什么也不值了

  1. 题目没有说给定的数据是有序的
  2. 选择的动物不能随便改变原数组顺序
  3. 总重量不超过的意思就是 <=

我们一般人考虑问题都是从简单到复杂,以循序渐进的方式进行,所以从选择1个动物开始分析

数组 1, 3, 5, 7, 9, 11, 21

index 0 1 2 3 4 5 6

定义两个数组

len - 能够选择的动物的数量

ends - 最后一只动物选定之后,累计的总重量

选择到第1只

数组长度,也就是动物的数量为 1 len[1]

因为当前就1只,左边没有动物,重量当然不可能超过自己 0 <= 1

算上自己的总重量 ends[1]


选择到第2只 重量3

左边 1 < 3,

动物的数量为 len[1, 2]

累计重量 ends[1, 4]


选择到第3只 重量5

左边 1 + 3 < 5

动物数量 len [1, 2, 3]

累计重量 4 + 5 = 9 ends[1, 4, 9]


选择到第4只 重量7

左边9 > 7

所以左边 累计重量应该选4合适 4 + 7 = 11 累计重量为11

动物数量继续保持在3 len[1, 2, 3, 3],

选择1, 3, 7, 累计重量 11 是否合适

1,3,7累计重量11, 1, 3, 5累计重量9,都是3只动物,

但是 9 比 11更合适,因为9更小,后面可以累加的动物数量更多

动物数量 len[1, 2, 3, 3]

累计重量 ends[1, 4, 9, 跳过] 第4只动物就会被跳过


选择到第5只 重量9

左边9 <= 9

动物数量 len[1, 2, 3, 3, 4]

累计重量 ends[1, 4, 9, 跳过, 18]


选择到第6只 重量11

左边 18 > 11

所以左边累计重量应该选9合适 9 + 11 = 20, 累计重量20

动物数量继续保持在4 len[1, 2, 3, 3, 4, 4],

选择1, 3, 5, 11, 累计重量 20是否合适

1,3,5,9累计重量18, 1,3,5,11 累计重量20, 都是4只动物,

但是 18 比 20更合适,因为18更小,后面可以累加的动物数量更多

动物数量 len[1,2,3,3,4,4]
累计重量 ends[1,4,9,条狗,18,跳过]


选择到第7只 重量21

左边 18 < 21

动物数量 len[1,2, 3,3, 4, 4, 5]

累计重量 ends[1,4,9, 跳过, 18, 跳过, 39]


最终索引到最后一只动物, 动物数量为5只

累计重量数组 ends[1,4,9, 跳过, 18, 跳过, 39]

最终纳入的动物为 1, 3, 5, 9, 21

实现

public class Algorithm0001 {

//    有n个动物重量分别a1,a2,a3....an,
//
//    这群动物一起玩叠罗汉游戏
//
//    规定从左往右选择动物,每只动物左边动物的总重量不超过自己的重量
//
//    返回最多能选多少个动物,求一个高效的算法
//
//    比如有7个动物,从左往右重量依次为 1,3,5,7,9,11,21
//
//    最多能选5个动物 1,3,5,9,21
//
//    注意:
//
//            - 实际给定的数组可能是无序的
//            - 要求从左往右选动物,且不能打乱原始数组

    public static int[] maxAnimal(int[] srcArray) {
        int index = 0; // 按顺序从第一个动物开始

        // 存储累计重量
        int[] ends = new int[srcArray.length];

        // 存储纳入的动物重量
        int[] valids = new int[srcArray.length];
        // 纳入的动物数量
        int validCount = 0;

        // 0- index, 1-validCount
        int[] opt = new int[2];
        opt[0] = index;
        opt[1] = validCount;

        conquer(srcArray, valids, ends, opt);

        index = opt[0];
        validCount = opt[1];
        int[] mArray = new int[validCount];
        for (int i = 0; i < validCount; i++) {
            mArray[i] = valids[i];
        }
        return mArray;
    }

    public static void conquer(int[] srcArray, int[] valids, int[] ends, int[] opt) {
        int index = opt[0];
        int validCount = opt[1];
        if (index < srcArray.length) {
            if (index == 0) {
                valids[validCount] = srcArray[index];
                ends[validCount] = srcArray[index];
                validCount++;

            } else {
                if (ends[validCount - 1] <= srcArray[index]) {
                    valids[validCount] = srcArray[index];
                    ends[validCount] = ends[validCount - 1] + srcArray[index];
                    validCount++;

                } else if (ends[validCount - 1] > srcArray[index]) {
                    if (validCount >= 2) {
                        // 比较累计重量数组 倒数第二项的累计重量+当前索引的动物重量 与 最后一项累计重量 的大小
                        if (ends[validCount - 1] > ends[validCount - 2] + srcArray[index]) {
                            // 说明 当前索引的动物 与 当前已纳入的最后一只动物 相比, 替换已纳入的最后一只动物 更好
                            valids[validCount - 1] = srcArray[index];
                            ends[validCount - 1] = ends[validCount - 2] + srcArray[index];
                        }
                        // else 说明 当前索引的动物 与 当前已纳入的最后一只动物 相比, 保持当前 已纳入的动物 更好, 继续索引下一只
                    } else {
                        // 当前只有1只动物纳入, 但是当前索引的动物重量 比 已纳入的唯一动物重量 小,应该把小的重量的动物纳入,替换掉原来的
                        valids[validCount - 1] = srcArray[index];
                        ends[validCount - 1] = srcArray[index];
                    }
                }
            }
            opt[0] = ++index;
            opt[1] = validCount;
            conquer(srcArray, valids, ends, opt);
        }
    }

    public static void main(String[] args) {
        int n = 1000;
        // 随机一些数
        List<Integer> mArrayList = new ArrayList();
        for (int i = 0; i < n; i++) {
            mArrayList.add((int) (Math.random() * 2 * n) + 1);
        }
        mArrayList.sort(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return (Integer) o1 - (Integer) o2;
            }
        });
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = mArrayList.get(i);
        }
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i]);
            System.out.print("  ");
            if (i % 10 == 0 && i > 0) {
                System.out.print("\n");
            }
        }

        System.out.print("\n");
        System.out.print("\n");

        int[] mArray = maxAnimal(array);
        for (int i = 0; i < mArray.length; i++) {
            System.out.print(mArray[i]);
            System.out.print("  ");
            if (i % 10 == 0 && i > 0) {
                System.out.print("\n");
            }
        }
    }
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 19:09:52  更:2022-07-20 19:12:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:22:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码