Python要求O(n)复杂度求无序列表中第K的大元素实例


Posted in Python onApril 02, 2020

昨天面试上来就是一个算法,平时基本的算法还行,结果变个法就不会了。。。感觉应该刷一波Leecode冷静下。。。今天抽空看下。

题目就是要求O(n)复杂度求无序列表中第K的大元素

如果没有复杂度的限制很简单。。。加了O(n)复杂度确实有点蒙

虽然当时面试官说思路对了,但是还是没搞出来,最后面试官提示用快排的思想

主要还是设立一个flag,列表中小于flag的组成左列表,大于等于flag的组成右列表,主要是不需要在对两侧列表在进行排序了,只需要生成左右列表就行,所以可以实现复杂度O(n)。

举个例子说明下步骤,比如有列表test_list=[6,5,4,3,2,1],找出第3大的元素,就是4,

如果flag=4:

l_list=[3,2,1]

r_list=[6,5]

因为第3大的元素,r_list长度为2,自然flag就是第3大的元素了,return flag,len(r_list)==k-1,就是结束递归的基线条件。

如果flag=1:

l_list=[]

r_list=[6,5,4,3,2]

问题就变成了求r_list里面第K大的元素了

如果flag=6:

l_list=[5,4,3,2,1]

r_list=[]

相当于求l_list里第k-(len(test_list)-len(r_list)+1)大的元素了,这里就是相当于求l_list=[5,4,3,2,1]第2大的元素

通过这三种情况进行递归,最终返回flag就是目标元素

最差复杂度就是n+n-1+n-2+n-3+......+1=(1+n)n/2,就是O(n²)

当时我就会回答出了最差复杂度肯定是n²啊,面试小哥说平均复杂度,我说计算平均复杂度好像很复杂吧?感觉他也有点蒙,就说每次都是二分的情况的复杂度,

当时竟然回答了个logn*logn。。。最后还是被面试管提示的。。。太尴尬了。。。

实际上如果每次刚好二分,第一次取flag比较次数是n,第二次是n/2,依次下去是n/4,n/8.....n/2

就是n+n/2+n/4....

最最丢人的是计算这个结果还想了一会。。。看样该做点高中上数学了。。。

实际结果自然是n(1+1/2+1/4+1/8+....1/2ⁿ)=2n,复杂度自然就是O(n)了

最后实现代码如下:

#给定一个无序列表,求出第K大的元素,要求复杂度O(n)
def find_k(test_list,k):
 flag=test_list[0]
 test_list.pop(0)
 l_list=[i for i in test_list if i < flag]
 r_list=[i for i in test_list if i >= flag]
 
 #结果递归的基线条件
 if len(r_list)==k-1:
  return flag
 elif len(r_list)>k-1:
  return find_k(r_list,k)
 else:
  #因为test_list.pop(0)让test_list少了一个元素,所以下面需要+1
  gap=len(test_list)-len(l_list)+1
  k=k-gap
  return find_k(l_list,k)
 
if __name__ == '__main__':
 test_list = [5, 4, 3, 2, 1,10,20,100]
 res=find_k(test_list,1)
 print(res)

补充知识:从N个数选取k个数的组合--不降原则(DFS)

原理 :不降原则(看代码前先看一下原理吧)

举个例子:

比如说在6里面随便选5个数,那么选法都是什么呢?

瞎枚举?

12345
12346

前两个还不会弄混

然后很可能就乱了

少点数可能不会乱

但是多了就不好整了

比如说在100里随便选50个数。

1 2 3 4 5 6 7 8 9 10 11 12…

所以我们可以运用不降原则:

保证枚举的这些数是升序排列

其实真正的不降原则还可以平

比如 1 2 2 3 3 4…

但是这里要说的“不降原则”不能平哦!

对于这道题也不能平

否则就有重复数字了

拿6个里面选3个举例子

1 2 3
1 2 4
1 2 5
1 2 6

第一轮枚举完毕。

第二个数加一

1 3 ?

这个“?”应该是4,因为是升序排列

1 3 4
1 3 5
1 3 6

接着,就是这样

1 4 5
1 4 6
1 5 6

第一位是1枚举完毕

第一位是2呢?

2 3 4
2 3 5
2 3 6
2 4 5
2 4 6
2 5 6

就是这样的,枚举十分清晰,对吗?

以此类推…

3 4 5
3 4 6
3 5 6
4 5 6

然后就枚举不了了,结束。

所以说,这样就可以避免判重了。

代码

#include<iostream>
#include<cstring>

using namespace std;
int n,k; //全局变量:从n个数的集合中选取k个数
int a[25]; //存放n个数的集合数据
int vis[25];//在dfs中记录数据是否被访问过
int re[25];//存放被选取的数字


void dfs(int step,int start)//参数step代表选取第几个数字,参数start代表从集合的第几个开始选
{
 if(step==k)//如果选够了k个就输出
 {
  for(int i=0;i<k;i++)
  {
   cout<<re[i]<<" ";
  }
  cout<<endl;
 }
 for(int i=start;i<n;i++)//不降原则的核心步骤1:从第i+1个开始选取数字(避免重选)
 {
  if(vis[i]==1)
   continue;
  vis[i]=1;
  re[step]=a[i];
  dfs(step+1,i+1); //不降原则的核心步骤2:从第i+1个开始选取数字(避免重选)
  vis[i]=0;
 }
 return;
}

int main()
{

 while(cin>>n>>k)
 {
  memset(a,0,sizeof(a));
  memset(re,0,sizeof(re));
  memset(vis,0,sizeof(vis));
  for(int i=0;i<n;i++)
  {
   cin>>a[i];
  }
  dfs(0,0);
 }
 return 0;
}

运行结果

Python要求O(n)复杂度求无序列表中第K的大元素实例

变形——从N个数中选取k个数求和(举一反三)

代码

#include<iostream>
#include<cstring>

using namespace std;
int n,k; //全局变量:从n个数的集合中选取k个数
int a[25]; //存放n个数的集合数据
int vis[25];//在dfs中记录数据是否被访问过
int re[25];//存放被选取的数字


void dfs(int step,int sum,int start)//参数step代表选取第几个数字,参数sum代表从选取前step-1个数时的总数,参数start代表从集合的第几个开始选
{
 if(step==k)//如果选够了k个就输出
 {
  cout<<re[0];
  for(int i=1;i<k;i++)
  {
   cout<<'+'<<re[i];
  }
  cout<<'='<<sum<<endl;
 }
 for(int i=start;i<n;i++)//不降原则的核心步骤1:从第i+1个开始选取数字(避免重选)
 {
  if(vis[i]==1)
   continue;
  vis[i]=1;
  re[step]=a[i];
  dfs(step+1,sum+a[i],i+1); //不降原则的核心步骤2:从第i+1个开始选取数字(避免重选)
  vis[i]=0;
 }
 return;
}

int main()
{

 while(cin>>n>>k)
 {
  memset(a,0,sizeof(a));
  memset(re,0,sizeof(re));
  memset(vis,0,sizeof(vis));
  for(int i=0;i<n;i++)
  {
   cin>>a[i];
  }
  dfs(0,0,0);
 }
 return 0;
}

运行结果

Python要求O(n)复杂度求无序列表中第K的大元素实例

变形——从N个数中选取k个数求积(举一反三)

代码

#include<iostream>
#include<cstring>

using namespace std;
int n,k; //全局变量:从n个数的集合中选取k个数
int a[25]; //存放n个数的集合数据
int vis[25];//在dfs中记录数据是否被访问过
int re[25];//存放被选取的数字


void dfs(int step,int sum,int start)//参数step代表选取第几个数字,参数start代表从集合的第几个开始选
{
 if(step==k)//如果选够了k个就输出
 {
  cout<<re[0];
  for(int i=1;i<k;i++)
  {
   cout<<'*'<<re[i];
  }
  cout<<'='<<sum<<endl;
 }
 for(int i=start;i<n;i++)//不降原则的核心步骤1:从第i+1个开始选取数字(避免重选)
 {
  if(vis[i]==1)
   continue;
  vis[i]=1;
  re[step]=a[i];
  dfs(step+1,sum*a[i],i+1); //不降原则的核心步骤2:从第i+1个开始选取数字(避免重选)
  vis[i]=0;
 }
 return;
}

int main()
{

 while(cin>>n>>k)
 {
  memset(a,0,sizeof(a));
  memset(re,0,sizeof(re));
  memset(vis,0,sizeof(vis));
  for(int i=0;i<n;i++)
  {
   cin>>a[i];
  }
  dfs(0,1,0);
 }
 return 0;
}

运行结果

Python要求O(n)复杂度求无序列表中第K的大元素实例

以上这篇Python要求O(n)复杂度求无序列表中第K的大元素实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Windows系统配置python脚本开机启动的3种方法分享
Mar 10 Python
Django中redis的使用方法(包括安装、配置、启动)
Feb 21 Python
Python使用logging模块实现打印log到指定文件的方法
Sep 05 Python
python学生信息管理系统(初级版)
Oct 17 Python
python训练数据时打乱训练数据与标签的两种方法小结
Nov 08 Python
Python从单元素字典中获取key和value的实例
Dec 31 Python
Python设计模式之解释器模式原理与用法实例分析
Jan 10 Python
使用Python向DataFrame中指定位置添加一列或多列的方法
Jan 29 Python
对Python函数设计规范详解
Jul 19 Python
django 简单实现登录验证给你
Nov 06 Python
python实现逢七拍腿小游戏的思路详解
May 26 Python
python 5个顶级异步框架推荐
Sep 09 Python
Pytorch 使用不同版本的cuda的方法步骤
Apr 02 #Python
pytorch 中的重要模块化接口nn.Module的使用
Apr 02 #Python
python递归函数求n的阶乘,优缺点及递归次数设置方式
Apr 02 #Python
PyTorch中的C++扩展实现
Apr 02 #Python
python实现将列表中各个值快速赋值给多个变量
Apr 02 #Python
Python运行提示缺少模块问题解决方案
Apr 02 #Python
Pycharm配置PyQt5环境的教程
Apr 02 #Python
You might like
PHP性能分析工具XHProf安装使用教程
2015/05/13 PHP
通过PHP自带的服务器来查看正则匹配结果的方法
2015/12/24 PHP
php redis实现对200w用户的即时推送
2017/03/04 PHP
PHP7 其他修改
2021/03/09 PHP
defer属性导致引用JQuery的页面报“浏览器无法打开网站xxx,操作被中止”错误的解决方法
2010/04/27 Javascript
正负小数点后两位浮点数实现原理及代码
2013/09/06 Javascript
jquery按回车提交数据的代码示例
2013/11/05 Javascript
Javascript自定义函数判断网站访问类型是PC还是移动终端
2014/01/10 Javascript
this,this,再次讨论javascript中的this,超全面(经典)
2016/01/05 Javascript
js实现textarea限制输入字数
2017/02/13 Javascript
react-native中ListView组件点击跳转的方法示例
2017/09/30 Javascript
JavaScript如何把两个数组对象合并过程解析
2019/10/10 Javascript
Vue+Node实现商品列表的分页、排序、筛选,添加购物车功能详解
2019/12/07 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
google广告之另类js调用实现代码
2020/08/22 Javascript
Windows系统下使用flup搭建Nginx和Python环境的方法
2015/12/25 Python
python中安装Scrapy模块依赖包汇总
2017/07/02 Python
django中的setting最佳配置小结
2017/11/21 Python
使用python实现knn算法
2017/12/20 Python
对python numpy数组中冒号的使用方法详解
2018/04/17 Python
Tensorflow加载预训练模型和保存模型的实例
2018/07/27 Python
python3中property使用方法详解
2019/04/23 Python
详解python中的time和datetime的常用方法
2019/07/08 Python
如何在python开发工具PyCharm中搭建QtPy环境(教程详解)
2020/02/04 Python
Pandas将列表(List)转换为数据框(Dataframe)
2020/04/24 Python
python实点云分割k-means(sklearn)详解
2020/05/28 Python
CSS3实现多样的边框效果
2018/05/04 HTML / CSS
写好自荐信的几个要点
2013/12/26 职场文书
一名老师的自我评价
2014/02/07 职场文书
高中军训感言600字
2014/03/11 职场文书
仓库文员岗位职责
2014/04/06 职场文书
让世界充满爱演讲稿
2014/05/24 职场文书
出差报告怎么写
2014/11/06 职场文书
2019新员工试用期转正工作总结范文
2019/08/21 职场文书
pytorch实现手写数字图片识别
2021/05/20 Python
iOS 16进一步确认,一共支持16款iPhone
2022/04/28 数码科技