当前位置: 首页 > news >正文

得到一个数组中任意X个元素的所有组合 即C(n,m)

一个面试题

一个数组 找出这样的三个元素 它们的和与目标值最接近

原始数组: [15, 27, 31, 33, 39, 44, 50, 57, 86, 91]
目标值: 98
这样的三个元素:15,33,50 (15+33+50=98)

算法

没有想到什么好的算法 可以快捷的找到这样的三个元素
只想到了穷举法 即

  • 找出所有的任意三元素 C(数组长度,3)

  • 放到优先队列中 按三个元素的和与目标值的差值(绝对值)进行排序

  • 第一个即是与目标值最接近的三元素

伪代码

// 得到所有的三元素组合列表 如["1,2,3", "4,5,6" , ...]
List<String> allUniqueThreeElements = getAllUniqueThreeElements(a,3);

// 三元素列表转成对象  对象中提供了这样的方法:getDiff (计算三元素的和与目标值的差值(绝对值))
List<ThreeElements> threeElementsList = new ArrayList<>();
for (String s : allUniqueThreeElements) {
    elementsList.add(new ThreeElements(s));
}
// 构造优先队列 按三元素的和与目标值的差值(绝对值)进行排序 优先队列默认大小为三元素组合列表大小
PriorityQueue<Elements> pq = new PriorityQueue<>(threeElementsList.size(),comparingInt(o -> o.getDiff(target))); 

// 将三元素组合对象 逐一放到优先队列中
for (ThreeElements e : threeElementsList) {
    pq.offer(e);
}

ThreeElements poll = pq.poll(); // 优先队列中 第一个即为要找的三元素

详细介绍

如何找到一个数组中的所有的X元素组合

即C(n,m)

如 数组 [1,2,3,4,5] 找出所有的元素组合

index01234
copy112345
copy212345
copy312345

相当于将同一数组复制三份 每一份中 取一个元素 不重复即可

这样的取法

copy1copy2copy3-
0121,2,3
0131,2,4
0141,2,5
015超过最大索引值 从前一位开始递增 同时逐个更新后面的值 即后一位的值 = 前一位 + 1
0231,3,4
0241,3,5
025超过最大索引值 从前一位开始递增
0341,4,5
035超过最大索引值 从前一位开始递增
045超过最大索引值 从更一位开始递增
1232,3,4
1242,3,5
125超过最大索引值 从前一位开始递增
1342,4,5
135超过最大索引值 从前一位开始递增
145超过最大索引值 从更一位开始递增
2343,4,5
235超过最大索引值 从前一位开始递增
245超过最大索引值 从更一位开始递增
345超过最大索引值 且此时不存在更前一位了 退出

对应的代码

    /**
     * 
     * @param indexArray 索引数组
     * @param maxIndexValue 最大索引值
     * @param startIndex indexArray中从此位开始递增
     * @return
     */
    private boolean next(final int[] indexArray, final int maxIndexValue, int startIndex){
//        System.out.println("indexArray: "+Arrays.toString(indexArray));
//        System.out.println("startIndex: "+startIndex);
        indexArray[startIndex]++; // 从此位开始递增
        if(indexArray[startIndex] > maxIndexValue){ // 超过最大索引值 从前一位开始递增
            return next(indexArray,maxIndexValue,startIndex-1);
        }else{
            // 同时逐个累加之后的元素 后一位的值 = 前一位+1
            for (int i = startIndex+1; i < indexArray.length; i++) {
                indexArray[i] = indexArray[i-1]+1;
                if(indexArray[i] > maxIndexValue){
                    if(startIndex -1 < 0){ // 如果是从第一位开始递增的 即不存在更前一位了 则退出递归
                        return false;
                    }
                    return next(indexArray,maxIndexValue,startIndex-1);
                }
            }
            return true;
        }
    }

测试代码

    @Test
    public void test_next(){
        // 测试从一个数组中得到所有的三元素组合
        int[] a = {1, 2, 3, 4, 5}; // 数组
        int maxIndexValue = a.length-1; // 最大索引值
        int[] indexArray = {0,1,2}; // 初始化索引数组
        int startIndex = indexArray.length-1; // 从末位开始递增

        // 验证  [0,1,2] --> [0,1,3]
        boolean next = next(indexArray, maxIndexValue, startIndex);
        assertTrue(next);
        assertArrayEquals(new int[]{0,1,3}, indexArray);

        // 验证 [0,1,4] --> [0,2,3]
        indexArray = new int[]{0, 1, 4};
        next = next(indexArray, maxIndexValue, startIndex);
        assertTrue(next);
        assertArrayEquals(new int[]{0,2,3}, indexArray);

        // 验证 [0,3,4] --> [1,2,3]
        indexArray = new int[]{0, 3, 4};
        next = next(indexArray, maxIndexValue, startIndex);
        assertTrue(next);
        assertArrayEquals(new int[]{1,2,3}, indexArray);

        // 验证 [2,3,4] --> X
        indexArray = new int[]{2, 3, 4};
        next = next(indexArray, maxIndexValue, startIndex);
        assertFalse(next);
    }

当验证其他一些极端情况的时候 如从一个数组中得到所有一个元素的组合 即C(n,1) 测试没有通过

    @Test
    public void test_next_and_only_choose_one_element(){
        // 测试一些更极端的情况 如 一个数组中选出所有1个元素的组合(C(n,1))
        final int[] a = {1, 2, 3, 4, 5};
        int maxIndexValue = a.length-1;
        int[] indexArray = {0};
        int startIndex = indexArray.length-1;


        //验证 [0] -> [1]
        boolean next = next(indexArray, maxIndexValue, startIndex);
        assertTrue(next);
        assertArrayEquals(new int[]{1},indexArray);
        System.out.println();
        // 验证 [4] -> X
        indexArray = new int[]{4};
        next = next(indexArray, maxIndexValue, startIndex);
        assertFalse(next);
    }

修复代码 将判断最后没有下一组的代码给提取出来了

    private boolean next(final int[] indexArray, final int maxIndexValue, int startIndex){
        if(startIndex < 0){ // 如果不存在更前一位了 则退出递归
            return false;
        }
        indexArray[startIndex]++; // 从此位开始递增
        if(indexArray[startIndex] > maxIndexValue){ // 超过最大索引值 从前一位开始递增
            return next(indexArray,maxIndexValue,startIndex-1);
        }else{
            // 同时逐个累加之后的元素 后一位的值 = 前一位+1
            for (int i = startIndex+1; i < indexArray.length; i++) {
                indexArray[i] = indexArray[i-1]+1;
                if(indexArray[i] > maxIndexValue){
                    return next(indexArray,maxIndexValue,startIndex-1);
                }
            }
            return true;
        }
    }

参考文档

http://wiki.jikexueyuan.com/p...

相关文章:

  • 事务隔离(二):基于加锁方式的事务隔离原理
  • mybatis随笔一之SqlSessionFactoryBuilder
  • 公司招聘
  • 在linux服务器上装svn版本管理,自动同步代码到项目根目录
  • web服务器配置及nginx和mysql部署
  • 2017.02.15
  • linux中的awk用法入门详解(二)
  • javascript事件失效l
  • 【Spark Summit East 2017】Spark,类型函数式编程的引诱者
  • linux命令大全之watch命令详解(监测命令运行结果)
  • Elasticsearch之更新(全部更新和局部更新)
  • mysql查看表结构
  • 使用Hilo.JS快速开发Flappy Bird
  • STAR法则
  • Openlayer4 - 最好最强大的开源地图引擎
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • Android 架构优化~MVP 架构改造
  • Git的一些常用操作
  • JavaScript DOM 10 - 滚动
  • Javascript编码规范
  • jquery ajax学习笔记
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 汉诺塔算法
  • 猴子数据域名防封接口降低小说被封的风险
  • 设计模式走一遍---观察者模式
  • 跳前端坑前,先看看这个!!
  • 小程序测试方案初探
  • 一个项目push到多个远程Git仓库
  • Hibernate主键生成策略及选择
  • 选择阿里云数据库HBase版十大理由
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • #Linux(帮助手册)
  • #Lua:Lua调用C++生成的DLL库
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (1)Nginx简介和安装教程
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (ibm)Java 语言的 XPath API
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (笔试题)分解质因式
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (强烈推荐)移动端音视频从零到上手(上)
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (转)EOS中账户、钱包和密钥的关系
  • (转载)PyTorch代码规范最佳实践和样式指南
  • .Mobi域名介绍
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .net core 6 redis操作类
  • .net 流——流的类型体系简单介绍