鱼C论坛

 找回密码
 立即注册
查看: 4446|回复: 76

对列表按照元素出现次数升序排序,要求空间复杂度为O(1)

[复制链接]
发表于 2020-6-7 14:48:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 在东边 于 2020-6-7 15:39 编辑

有一个列表,假设为

  1. nums = [1, 3, 2, 1, 3, 1]
复制代码


按照元素出现次数升序排序,排序结果应该是

  1. [2, 3, 3, 1, 1, 1]
复制代码


可以在空间复杂度为 O(1) 的前提下,实现这样的排序算法吗?

下面这两种方法是不可行的:

1.

  1. nums.sort(key=nums.count)
复制代码


执行上面代码后,发现 nums 还是原来的 nums

看了下 Python 官方文档关于 list.sort 的介绍

里面提到

CPython implementation detail: 在一个列表被排序期间,尝试改变甚至进行检测也会造成未定义的影响。 Python 的 C 实现会在排序期间将列表显示为空,如果发现列表在排序期间被改变将会引发 ValueError。


排序期间列表显示为空,所以在对 nums 调用 sort 方法时,nums 始终为 [],nums.count 始终返回 0,因此 nums 未发生改变

2.

  1. nums.sort(key=nums[:].count)
复制代码


上面这行代码可以达到按元素出现次数排序,但由于使用列表的切片 nums[:],创建了一份拷贝,空间复杂度不是 O(1)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-6-7 14:58:12 | 显示全部楼层

回帖奖励 +10 鱼币

本帖最后由 Twilight6 于 2020-6-7 15:07 编辑



这样的空间复杂度算 O(1) 吧
  1. nums = [1, 2, 3, 1, 2, 1]
  2. nums.sort()
  3. nums.reverse()
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:12:05 | 显示全部楼层

回帖奖励 +10 鱼币

基础
  1. nums.sort(reverse=True)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:17:38 | 显示全部楼层

学到了,我居然不知道还有这种用法
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:19:02 | 显示全部楼层
Twilight6 发表于 2020-6-7 15:17
学到了,我居然不知道还有这种用法

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:19:14 | 显示全部楼层
Twilight6 发表于 2020-6-7 14:58
这样的空间复杂度算 O(1) 吧

要看 sort 内部的实现。
基本上,时间复杂度在 O(nlogn) 的排序算法,空间复杂度都是不 O(1)。
而时间复杂度在 O(n^2) 的排序算法,空间复杂度是 O(1)。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-7 15:20:12 | 显示全部楼层

看来这个 nums = [1, 2, 3, 1, 2, 1] 不太恰当

如果是下面这样呢

  1. nums = [3, 2, 1, 3, 2, 3]
复制代码

  1. nums.sort(revere=True)
复制代码


排完后,是 [3, 3, 3, 2, 2, 1]

可是按元素出现次数排序,应该是 [1, 2, 2, 3, 3, 3]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:28:35 | 显示全部楼层
。。。才看见楼主说的是按出现次数排序
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:31:15 | 显示全部楼层
在东边 发表于 2020-6-7 15:20
看来这个 nums = [1, 2, 3, 1, 2, 1] 不太恰当

如果是下面这样呢

这个空间复杂度很低了
  1. from collections import Counter
  2. nums.sort(key=Counter(nums).__getitem__)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

 楼主| 发表于 2020-6-7 15:37:13 | 显示全部楼层
永恒的蓝色梦想 发表于 2020-6-7 15:31
这个空间复杂度很低了

假设这个列表长度为 n,里面每个元素都只出现 1 次(最坏情况)

那么使用 Counter 实例化后的对象长度也为 n

空间复杂度就是 O(n)

其实,我觉得吧,只要引入了新的容器对象,不管是 list,Counter 还是其他

空间复杂度都不可能是 O(1) 了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:42:43 | 显示全部楼层
时间复杂度在 O(n^2) 的排序算法,空间复杂度是 O(1)。

可以很简单的实现啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-7 15:50:44 | 显示全部楼层
Stubborn 发表于 2020-6-7 15:42
时间复杂度在 O(n^2) 的排序算法,空间复杂度是 O(1)。

可以很简单的实现啊

我是要按照元素出现次数排序,不是要按照元素大小排序

要想知道每个元素出现多少次,那至少得遍历一遍,然后存在某个容器里,再根据次数排序吧

既然产生了新的容器,空间复杂度就不是 O(1) 了

或者是有什么我没想到的方法吧。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:51:33 | 显示全部楼层
效率炸裂
  1. def sort(list):
  2.     flag=True
  3.     robj=range(1,len(list))
  4.    
  5.     while flag:
  6.         flag=False

  7.         for i in robj:
  8.             if list.count(list[i])<list.count(list[i-1]):
  9.                 list[i],list[i-1]=list[i-1],list[i]
  10.                 flag=True
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 15:56:14 | 显示全部楼层

回帖奖励 +10 鱼币

无法实现
按照频率排序原列表,至少需要三步,
1. 统计每个元素的频率
2. 对频率排序
3. 将频率的顺序,映射到实际元素

所以,空间复杂度至少为 O(n),时间复杂度为 O(nlogn)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 16:40:05 | 显示全部楼层
我只会这两种方法,应该是O(1)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 16:56:31 | 显示全部楼层

回帖奖励 +10 鱼币

本帖最后由 Stubborn 于 2020-6-7 17:11 编辑

假设一个问题,

nums = [3, 2, 1, 3, 2, 3]

这个数组,第一个排序后,不管大小位置,我只把相同的排列到一起。产生如下序列

nums = [3, 3, 3, 2, 2,1]

出现次数升序排序,知道,最低是出现一次,换而言之,不用管其他的顺序

我扫描数组,把出现一次的,list.insert(index=0, obj),

记录已经处理的长度len1,处理完一个+1.和一个“阶层”长度(default=0,当一个处理完,开始处理2次,更新为第一次出理完的长度)《处理的长度,用于记录下一‘’层;次该插入的位置,以及程序进度》《“阶层”的长度用于插入的位置》





小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 18:21:52 | 显示全部楼层

回帖奖励 +10 鱼币

新手看不懂,什么是空间复杂度?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 19:48:44 | 显示全部楼层

挣个10鱼币,不容易啊!{:10_295:}

本帖最后由 Stubborn 于 2020-6-7 20:20 编辑


  1. def SorteTimeComplexityOne(Array):
  2.     length = len(Array)
  3.     idx = 2

  4.     # TODO 数组排序,一样的放在一起。
  5.     while length > idx:
  6.         val = Array[idx]
  7.         val_idx = Array.index(val)

  8.         if val_idx < idx:
  9.             del Array[idx]
  10.             Array.insert(val_idx, val)

  11.         idx += 1

  12.     # TODO {
  13.     #    Array: [1, 1, 1, 6, 2, 2, 2, 3, 3, 5, 5]
  14.     #    success : 已经处理完的元素长度
  15.     #    task : 任务长度
  16.     #    insert_idx : 插入位置
  17.     #    idxl : 左侧索引
  18.     #    idxr : 右侧索引
  19.     #  }
  20.     success = 0
  21.     insert_idx=0
  22.     task = 1
  23.     idxl = 0
  24.     idxr = 1

  25.     while length > success:

  26.         if idxr < length and Array[idxl] == Array[idxr]:
  27.             idxr += 1
  28.         else:
  29.             if task == idxr - idxl:

  30.                 while idxr - idxl:
  31.                     val = Array[idxl]
  32.                     del Array[idxl]
  33.                     Array.insert(insert_idx, val)
  34.                     idxl += 1
  35.                     success += 1
  36.             else:
  37.                 idxl = idxr

  38.             if idxl >= length:
  39.                 idxl= idxr= insert_idx  = success
  40.                 task += 1

  41.     print(Array)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 19:56:22 | 显示全部楼层

回帖奖励 +10 鱼币

看不懂
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-7 19:56:24 | 显示全部楼层
赚小钱 发表于 2020-6-7 15:56
无法实现
按照频率排序原列表,至少需要三步,
1. 统计每个元素的频率

瞅瞅18楼的,时间,空间复杂度是多少
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-19 14:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表