一.引言

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例:

输入: n = 4 k = 2
输出: [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4]]

n=4 代表待组合 list = [1,2,3,4]

二.递归调用

1.方法参数

combine 为主方法,getCombine 为实际递归调用的方法,主要有5个参数:

res[list] : 保存存储结果

prefix[lsit] : 保存当前前缀

n : 给定数字,代表1-n的数字范围

k : 代表组合的个数

start : 标识当前起始位置

2.方法思路

采用递归的方式遍历

(1) 从1开始固定位置作为前缀,随后遍历1之后的元素并添加到前缀中

(2) 当 k = 0 时代表此时前缀的长度已达到预定长度 k,此时将 prefix 添加到 result

(3) 随后执行 pop 操作,删掉前缀最后一位并将 start 加1,相当于固定另外一个数字继续遍历

(4) 当 start 大于 n 时代表遍历完全部数组元素,

class Solution(object):def combine(self, n, k):res = []self.get_combine(res, [], n, k, 1)return resdef get_combine(self, res, prefix, n, k, start):if k == 0:res.append(list(prefix))elif start <= n:prefix.append(start)self.get_combine(res, prefix,n, k - 1, start + 1)prefix.pop()self.get_combine(res, prefix,n, k, start + 1)

上面的思路其实还是比较晦涩,下面结合运行日志理一下:

A.代表最开始固定第一位并向后寻找

前进:函数从 k = 2 , start = 1 开始,此时前缀 append 得到 [1],这里注意,当前长度 k 和 前缀 prefix 有一个关系,即 当前长度 K + 前缀 len(prefix) = k = 2,所以当前长度 K 为0是,代表此时 len(prefix) = k = 2,即找到一个满足条件的结果,所以添加到 result

回退:当 k = 0 时,结束当前结构体,返回上一层递归,随后执行 prefix.pop 删除最后一个元素,并将 start + 1,继续向后探索,所以 prefix = [1,2] => [1],然后 start = start + 1 = 3,此时 k=1,继续递归 start = 3 加入 prifix [1] => [1,3] ,k = 1 -> 0 继续保存,随后寻找下一个数字

B.代表固定位置的数字的所有可能遍历完毕,继续固定下一个数字

[1,2],[1,3],[1,4] 添加完毕后,1 的所有可能已经结束了,一直回退程序直到 prefix -> [],此时开始执行 start + 1,即前缀变为 [2],然后固定2,往后找3,找4,随后回退直到 prefix -> [],再从3开始

C.代表任务结束

当 [3,4] 添加到结果并且 prefix pop 到 [] 时,要开始固定下一个位置,此时 k = 2,start = 5 始终 > n = 4,所以程序不再递归,直到退出并返回 res

三.全排列

1.方法思路

如果上面不好理解,其实还有偷懒的方法 : 对 1-n 的数字全排列随后截断去重,给定 n = 4, k = 2

(1) 对数组 [1,2,3,4] 全排列得到全排列全部结果:

[[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4],...[4, 1, 2, 3]]

(2) 随后将取全排列数组 top-k:

[[1, 2], [1, 2], [1, 3],...[4, 1]]

(3) 然后去重 "12","12","13",...,"41" 得到:

{'12', '24', '34', '23', '14', '13'}

2.实现

全排列之前介绍了几种方法在: 求数组全排列 中,这里给出其中一种方法,回朔法:

def solveByBackTrack(nums):def backtrack(position, end):if position == end:res.append(nums[:])returnfor index in range(position, end):nums[index], nums[position] = nums[position], nums[index]backtrack(position + 1, end)nums[index], nums[position] = nums[position], nums[index]res = []backtrack(0, len(nums))return resdef getArrangeByBackTrack(n, k):nums = list(range(1, n + 1))candidates = set() # 去重results = solveByBackTrack(nums) # 全排列for i in results:tmp = i[:k] # 截断tmp.sort()candidates.add(''.join(list(map(lambda x: str(x), tmp))))return candidates# 全排列
n = 4
k = 2
re = getArrangeByBackTrack(n, k)
print(re)
{'12', '13', '24', '14', '23', '34'}

全排列截断虽然思路清晰,但是随着 n 的增加,堆栈的递归深度和线程占用非常严重,这里仅供偷懒,不做实际使用

四.API-itertools

itertools 提供 combinations 方法可以直接获取对应排列,如果不是做题而是学习工作中有需求可以直接调用该方法:

import itertoolsn = 4k = 2nums = list(range(1, n+1))can = list(itertools.combinations(nums, k))print(can)
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

五.耗时

常规 n, k

n k cost
递归 4 2 1.9311904907226562e-05
全排列 4 2 4.1961669921875e-05
API 4 2 4.76837158203125e-06

n >> k

n k cost
递归 20 2 0.00011992454528808594
全排列 20 2 so loooooooooooooooong...
API 20 2 3.910064697265625e-05

该用哪个不该用哪个很明显了吧 ~

Python - 返回 1:n 中所有可能的 k 个数的组合相关推荐

  1. JAVA算法:给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合(JAVA)

    JAVA算法:给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合(JAVA) 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合.. 当 n = 4 ...

  2. topK问题——N个数中取最大的K个数

    topK问题 在海量数据中找出出现频率最高的前k个数,或者从海量数据中找出最大的前k个数,这类问题通常被称为topK问题. N个数中取最大的K个数,用小根堆:N个数中取最小的K个数,用大根堆:时间复杂 ...

  3. Python递归实现①把嵌套列表压平为一层列表②返回嵌套列表中某元素出现的个数③返回第n个斐波那契数

    一.把嵌套列表压平为一层列表 def flatten(nested_list):'''这是把嵌套列表压平为简单列表并返回的函数:参数 nested_list:一个嵌套列表'''#先定义一个空列表,用于 ...

  4. 找出一堆数中最小的前K个数

    描写叙述: 给定一个整数数组.让你从该数组中找出最小的K个数 思路: 最简洁粗暴的方法就是将该数组进行排序,然后取最前面的K个数就可以. 可是,本题要求的仅仅是求出最小的k个数就可以,用排序能够但显然 ...

  5. 单向链表中查找倒数第K个数

    问题 单向链表如果要找某一元素或者遍历链表,只能从头节点开始,所以如果我们用普通方法查找倒数第K个数,要分两步:第一步:先遍历链表中元素的个数,第二步:从头开始遍历,遍历到链表个数-k个数; 用两个指 ...

  6. 大顶堆,n个数中找最小的k个数

    package com.alo.offer;import java.util.Scanner;/*** n个数中找到最小的m个数 使用大顶堆* n个书中找到最大的m个数 使用小顶堆* @author ...

  7. Python从N个数中找到最大的K个数

    提出问题: 如何在某集合里面找出最大或最小的K个元素. 解决思路: 找出最大或最下的K个元素,可以使用Python库中的heapq模块,该模块提供两个函数nlargest()求最大K个和nsmalle ...

  8. java第k大的数字,JAVA中寻找最大的K个数解法

    这个题拿到之后首先会想到排序,排好序之后在选取选取最大的K个数.排序选择快速排序是个比较好的选择. 好了,让我们来进行第一个解法:快速排序 代码如下 复制代码代码如下: public static v ...

  9. python链表中删除一个节点数据_python实现单链表中删除倒数第K个节点的方法

    本文实例为大家分享了python实现单链表中删除倒数第K个节点的具体代码,供大家参考,具体内容如下 题目: 给定一个链表,删除其中倒数第k个节点. 代码: class LinkedListAlgori ...

最新文章

  1. HDU Problem - 4280 Island Transport(最大流)
  2. 通过制定编码规范的过程来说明《学会放弃、妥协也是个大进步,也是相当的提高工作效率》...
  3. Go语言程序记录日志
  4. oracle_Grid Infrastructure 启动的五大问题
  5. 项目复制引起的访问路径与项目名不一致
  6. C# CommandName四个属性
  7. java 股票数据接口_股票数据查询接口
  8. ASEMI整流桥S35VB100参数规格,S35VB100封装尺寸
  9. 高通骁龙845的android手机有哪些,骁龙845手机买什么好 目前6款最值得买的骁龙845手机推荐...
  10. H3C 双线路 nqa 联动
  11. 省电指南-ESP8266如何降低功耗
  12. 用mac原生的日历和automator,实现定时发微信
  13. 场景分析法设计测试用例
  14. 西安交通大学计算机学院贾宇轩,CCF西安交通大学学生分会成立
  15. aspen压缩因子_利用aspen plus进行物性参数的估算讲解
  16. 309 Best Time to Buy and Sell Stock with Cooldown
  17. android gps locationCb 数据
  18. jsonPath解析测试
  19. Jetson Nano配置YOLOv5并实现FPS=25
  20. 桌面云计算机有没有处理器,云桌面延伸成云电脑,电脑是否真的要被淘汰?

热门文章

  1. python爬虫完整代码下载页
  2. JAVA计算机毕业设计学术会议信息网站Mybatis+源码+数据库+lw文档+系统+调试部署
  3. 不要再说Qt教程少了
  4. Linux查看硬盘信息方法总结
  5. 《俗人笔记》之《Java基础语法上》
  6. 程序员自学编程,推荐一些高质量自学网站?
  7. 怎样输入字符型数据技巧
  8. Java例:计算某年某月有多少天
  9. 补码 符号数的二进制 整数
  10. Linux命令学习之五