如何将n个数分成K组

Toanso 2011-09-04 07:57:30
有n个数,n可以不是很大,假设n个数全是实数,
将n个数均分成K个组,(假设 n%k==0 )每个组有n/k个数
假设这个组为m1,。。。。mk;

使得 m1中的数<m2中的数<....<mk中的数。 但每个单独组m中的数不一定需要有序。。



第一想到的就是 先排序,然后不断取。。。肯定不是最优
大家有啥好办法不?
...全文
2071 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
ischarles 2011-09-08
  • 打赏
  • 举报
回复
用桶排序即可完成
Toanso 2011-09-08
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 we_sky2008 的回复:]
将数组分割为k部分,使前面的部分的值不大于后面部分的值即可,每个部分的各元素不必是有序的
C++的话可以直接使用算法库中的nth_element函数,这里我自己用C实现了一遍
其实归根结底,这个题目还是求N个数种最小的K个数

C/C++ code

#include<stdio.h>
#include<stdlib.h>

//三点中值
int get_mid(int _1s……
[/Quote]
这算法复杂度多少啊。。。求问,快排的话 应该O(nlogn)+n
wangzhen11aaa 2011-09-05
  • 打赏
  • 举报
回复
1、用实数整数部分作为下标构建数组。然后重新分配数组的长度为k.
2、再用根据实数部分的顺序依次存入每个数组中:例如3.1放入A[3]中,假如3.x一共有小于k个数那么,考虑将后面的4.x放入A[3]中。依次类推。直到末尾。
never517 2011-09-05
  • 打赏
  • 举报
回复
n里面如果有重复多次的一个数,上面的方法都是枉然
蓝鹰 2011-09-05
  • 打赏
  • 举报
回复
先确定每组有多少个数,
然后进行快速排序:
先从所有数中取出最小(最大)的数,放在第一组,接着再从剩余的数中取出最小(最大)的数
重复以上过程,直到这一组装满,然后对下一组进行同样的操作,直到所有组都被装满!
超级大笨狼 2011-09-05
  • 打赏
  • 举报
回复
有n个数,n可以不是很大,假设n个数全是实数,


这样的提示,就是等于说,构建一个n长的数组,取整为下标,丢桶里。
桶里再搞个有序小堆,避免命中冲突。
O(n)桶排序
顺次拿出,就是排序,有了序,想怎么分都可以,随便玩了。
weareu 2011-09-04
  • 打赏
  • 举报
回复
int m[k][n/k];k个组,每个组n/k个元素,m[0]指向最小的那个组,以此类推;
从原数组中取出前k个数作为基准;按从小到大的顺序分别放入m[0][0],m[1][0],m[2][0]...m[k][0];
然后从第k+1个数开始分别跟k个基准进行比较放入相应的基准后面,如果某一个组满了就向下组或上组转移数据;
这样,遍历一遍就行了,可能比较的次数会多一点,效率不稳定
we_sky2008 2011-09-04
  • 打赏
  • 举报
回复
当然也可以使用最大堆来求N个数种最小的K个数,
we_sky2008 2011-09-04
  • 打赏
  • 举报
回复
将数组分割为k部分,使前面的部分的值不大于后面部分的值即可,每个部分的各元素不必是有序的
C++的话可以直接使用算法库中的nth_element函数,这里我自己用C实现了一遍
其实归根结底,这个题目还是求N个数种最小的K个数

#include<stdio.h>
#include<stdlib.h>

//三点中值
int get_mid(int _1st, int _2nd, int _3rd)
{
if ((_2nd <= _1st && _1st <= _3rd) || (_3rd <= _1st && _1st <= _2nd))
return _1st;
if ((_1st <= _2nd && _2nd <= _3rd) || (_3rd <= _2nd && _2nd <= _1st))
return _2nd;

return _3rd;
}

//插入排序
void my_sort(int *f, int *l)
{
int *i, *j;

for (i = f; i < l; ++i)
{
int tmp = *i;

for (j = i; j > f; --j)
{
if (tmp < *(j - 1))
*j = *(j - 1);
else
break;
}

*j = tmp;
}
}

//分割函数,保证小于mid的元素排在大于mid的元素的前面
int *my_partition(int *f, int *l, int mid)
{
int tmp;

while (f < l)
{
while (*f < mid)
++f;
while (*--l > mid)
;

if (!(f < l))
return f;

tmp = *f;
*f++ = *l;
*l = tmp;
}

return f;
}

//如果是C++的话,可以直接使用算法库中的nth_element函数,就不需要自定义这个函数了
void my_find_nth_element(int *f, int *nth, int *l)
{
while (f + 3 < l)
{
int *cut = my_partition(f, l, get_mid(*f, *(l - 1), *((l - f) / 2 + f)));

if (cut <= nth)
f = cut;
else
l = cut;
}

my_sort(f, l);
}

void func(int *f, int *l, int k)
{
int i, j;
int len;

if (NULL == f || NULL == l || l <= f || ((l - f) % k))
return;

//分割为k部分
for (i = 0, len = (l - f) / k; i < k - 1; ++i)
{
my_find_nth_element(f + i * len, f + (i + 1) * len, l);
}

//打印分割后每部分的值
for (i = 0; i < k; ++i)
{
for (j = 0; j < len; ++j)
{
printf("%d\t", f[i * len + j]);
}
printf("\n");
}
}

int main()
{
int a[] = {10, 13, 20, 12, 15, 9, 3, 19, 23, 2, 21, 5, 4, 14, 17, 16, 1, 7, 22, 8, 0, 6, 11, 18};

func(a, a + sizeof(a) / sizeof(a[0]), 4);

system("pause");
return 0;
}


showjim 2011-09-04
  • 打赏
  • 举报
回复
把快排改造一下,也就是限制一下结束条件,当区间内没有需要查找的点就停止
Toanso 2011-09-04
  • 打赏
  • 举报
回复
就是 n个数随便你怎么取 只要分成k组 每一个组保证是n/k个数 并且 这些组的 是有序的

组有序的意思是 组1中的数都比2小 组2 中的数都比组3中的数小。。

比如 n = {2,1,4,5,6,8,49,1};k = 2
可以分为两组 一组为{2,1,4,1} 和 {5,6,8,49}
即:组一中的数 比组2中的数小 但是组内数不必有序
HelloGameProgramer 2011-09-04
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 news080 的回复:]

感觉是快排。
要是事先知道分成情况的话,尝试下桶排序
[/Quote]
分布情况
liyiying 2011-09-04
  • 打赏
  • 举报
回复
问题还不是太清楚,能否说得详细点.

你是随机取出,还是有次序地取出.
HelloGameProgramer 2011-09-04
  • 打赏
  • 举报
回复
感觉是快排。
要是事先知道分成情况的话,尝试下桶排序

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧