0000到9999取ID的算法

panwl83 2015-07-29 09:24:27
0000到9999的所有数字生成ID,从0数到9999共10000个数,0即0000,1即0001,2即0002,...9999
用过的ID存入数据库,现在算法要解决的问题是排除用掉的ID,然后从剩下的可用ID中随机给出一个。

楼主用php实现如下:
第一步:
for循环出所有ID放入数组,结果如下
$all = [0001,0002,……,9999]
第二步:
先select查询出已经使用的ID放到数组,如下假定0001,0002已使用过,通过对查询结果遍历的方式放入数组
$used = [0001,0002]
第三步:
两层遍历$all、$used,移除0001,0002,得到剩余可用ID数组,结果如下
$left = [0003,……,9999]
第四步:
php自带函数实现随机从数组中取出一个元素的方法获得新ID并新增到数据库。
$rndKey = array_rand($left)
$newID = $arr[$rndKey]

看看哪里还能优化,还有这么多元素,用数组靠谱吗?
或者哪位大牛有更好的算法解决这样的需求?
...全文
848 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
三仙半 2015-08-17
  • 打赏
  • 举报
回复
还是用个表把可用ID存起来吧,用一个删除一个,我要是遇到这样的事情肯定会这么做。
lx3275852 2015-08-14
  • 打赏
  • 举报
回复
引用 3 楼 panwl83 的回复:
[quote=引用 1 楼 li_x1979 的回复:] ID一般没有这样用的。都是设置一个计数器,一直往上加。分配过了的不好再重新使用,就好像身份证号码一样。如果非要这样用,那建两张表,一张存未分配的,一张存使用过的。
原先是你说的这样做的,奇葩客户要求改随机的。。。[/quote] 我倒是有个方法,你可以参考一下。但是我不会php,用伪代码给你描述一下。。前两步和你一样 第一步,和你一样,初始化数组 $all = [0000,0001,……,9999] 第二步,从数据库里读,也和你一样。 $used = [1234,3333,0007,0001,5678] 元素个数5 第三步,变量i,遍历all数组,used[i]和i分别作为下标,做swap操作,如i=0时,all[0]和all[1234]交换,接下来i=1时,all[1]和all[3333]交换.. 交换结果是$all = [1234,3333,0007,0001,5678,0005,0006,0002,0008……,9999] ps:注意0007位置已经和0002换了位置了 第四步,产生随机数(因为used元素个数是5,所以随机数是[5,9999]闭区间的随机数.) 比如随机数是8,则all[5]和all[8]swap,并且used添加元素0008,并插入数据库 操作的结果是 $all = [1234,3333,0007,0001,5678,0008,0006,0002,0005……,9999] $used = [1234,3333,0007,0001,5678,0008] 元素个数6 再接下来和第四步一样,但是因为used元素个数是6了,所以要产生[6,9999]的随机数.. 之后的不用我说了吧,你应该理解了. 整体算法时间复杂度应该是最低的了
Turing_0 2015-08-07
  • 打赏
  • 举报
回复
M序列 M序列
涛锅 2015-08-06
  • 打赏
  • 举报
回复
这样的话,我觉得你应该先将所有id先存到数据库,用掉一个就标记一个。
erqieshi 2015-08-05
  • 打赏
  • 举报
回复
当然 其实也可以不用预处理随机 的 参照random_shuffle 初始 0,1,2,3,,,,,,9999 记作a0,a1,,,,,,a9999 第0次 rand%10000 r0取第0位的数跟r0位的数交换 取交换后的a0就是随机ID 第1次 rand%9999 随机出索引r1,取第1位的数跟r1位的数交换 取交换后的a1就是随机ID , , ,第k次 rand%(10000 - k) 随机出索引rk,取第k位的数跟rk位的数交换 取交换后的ak就是随机ID 这个算法 也是O(1)的时间复杂度 O(n)的空间复杂度
erqieshi 2015-08-05
  • 打赏
  • 举报
回复
该算法 预处理 O(n) 后续O(1) 不可能有更好效率的了 并且 每次取ID随机 跟预处理随机 客户是根本没办法区别的 任何黑盒测试都没办法测试出来 当然 你预处理随机的时候, 用的伪随机算法被人摸索到规律就另论 比如 用的是同一个随机key
erqieshi 2015-08-05
  • 打赏
  • 举报
回复
预处理一次随机打乱0~9999 保存 ID 0,1,2,,,,9998,9999 预处理后 ID_RandShuffle 8993,2,1998,2015,,,,,,, 每次++ 从ID_RandShuffle拿
欢乐的小猪 2015-08-05
  • 打赏
  • 举报
回复
你把没用过的ID存起来呗。这样1到3步就都省了
Tiger_Zhao 2015-07-31
  • 打赏
  • 举报
回复
前三步可以简化:

查询已使用的ID(按从小到大排序),保持这个游标,不用放到数组中。
ID从0000到9999循环 {
  如果 ID=游标当前ID(已使用),游标前进一条
  否则(ID<游标当前ID OR 游标已空),ID加入数组$left
}
li_x1979 2015-07-30
  • 打赏
  • 举报
回复
ID一般没有这样用的。都是设置一个计数器,一直往上加。分配过了的不好再重新使用,就好像身份证号码一样。如果非要这样用,那建两张表,一张存未分配的,一张存使用过的。
panwl83 2015-07-30
  • 打赏
  • 举报
回复
引用 1 楼 li_x1979 的回复:
ID一般没有这样用的。都是设置一个计数器,一直往上加。分配过了的不好再重新使用,就好像身份证号码一样。如果非要这样用,那建两张表,一张存未分配的,一张存使用过的。
原先是你说的这样做的,奇葩客户要求改随机的。。。
chmuggmwtg 2015-07-30
  • 打赏
  • 举报
回复
用list之类的,先全放进去,用一个删一个,会不会简单点

33,006

社区成员

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

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