C语言的最小可分配ID【四种解法】

题目:找到一个乱序列表里面最小可分配的ID号,ID唯一且非负

解法一:

​ 从0开始遍历,判断x是否是列表中的数,是的话换下一个数判断。如果不是,则是最小可分配ID.

int judege_num(int target, int arr[])
{
    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
        if (arr[i] == target) {
           return false;
        }
    }
    return true;
}

int find_num(int lst[])
{
	int i=0;
	while(1)
	{
		int flag=judge_num(i,lst);
        if(flag)
        {
            return i;
        }
        i++;
	}
}

解法二:

​ 对于n个ID,如果存在小于n的可用ID,必然存在某个ID不在[0,n)这个范围内。否则这些ID⼀定是0到(n-1)的某个排列,这种情况下,最小的可用ID是n。
​ 简单来说就是现在有十七个人(每个人有自己的编号&&随便坐),他要么坐满0~16号座位,要么有人坐到16号以后。

​ 使用⼀个长度为n + 1的数组,来标记区间[0,n]内ID是否可用,长度为n+1是因为n-0+1。由于只有可用/不可用两种状态,可以用位标记状态。
​ 初始化数组->小于n则标为1->遍历从0到 n 的所有数字,第一个未标记的数字就是最小的缺失非负整数,将其返回

#define N 1000000 // 1 million
#define WORD_LENGTH sizeof(int) * 8
void setbit(unsigned int* bits, unsigned int i) {
	bits[i / WORD_LENGTH] |= 1<<(i % WORD_LENGTH);
}
int testbit(unsigned int* bits, unsigned int i) {
	return bits[i/WORD_LENGTH] & (1<<(i % WORD_LENGTH));
}
unsigned int bits[N/WORD_LENGTH+1];
int min_free(int* xs, int n) {
	int i, len = N/WORD_LENGTH+1;
	for(i=0; i<len; ++i)
		bits[i]=0;
	for(i=0; i<n; ++i)
		if(xs[i]<n)
			setbit(bits, xs[i]);
	for(i=0; i<=n; ++i)
		if(!testbit(bits, i))
			return i;
}

​ 优化一般从时间和空间考虑,解法二使用数组,用空间换取了时间,数组很大的时候,空间带来的性能问题不得不考虑。

解法三:

将问题分解,ID值小于等于n/2(向下取整)的放序列1,其余放序列2.

还是用座位比喻,演唱会有分区,第一个区域坐满,第二区域(从n/2向下取整+1到n)肯定有空位置。

分而治之:http://t.csdnimg.cn/br7FF

用归并排序理解分而治之:将序列分组,组内排序后,合并排序,直至最后一次合并排序。

使用递归的方式,减小问题规模。函数入口参数增加上下界下标。

#include <stdio.h>
#include <limits.h>

int find_min_available_id(int arr[], int start, int end) {
    if (start == end) {
        return arr[start];
    }

    int mid = (start + end) / 2;
    int left_min = find_min_available_id(arr, start, mid);
    int right_min = find_min_available_id(arr, mid + 1, end);

    return left_min < right_min ? left_min : right_min;
}

int main() {
    int arr[] = {5, 3, 8, 1, 6};
    int n = sizeof(arr) / sizeof(arr[0]);

    int min_id = find_min_available_id(arr, 0, n - 1);
    printf("The minimum available ID is: %d", min_id);

    return 0;
}

解法四:

优化解法三的栈较大的问题,采用迭代的方式替代递归:

int min_free(int* xs, int n) {
	int l=0;
	int u=n-1;
	while(n) {
		int m = (l + u) / 2;
		int right, left = 0;
		for(right = 0; right < n; ++ right)
			if(xs[right] <= m) {
				swap(xs[left], xs[right]);
				++left;
			}
			if(left == m - l + 1) {
				xs = xs + left;
				n = n - left;
				l = m+1;
			} else {
				n = left;
				u = m;
			}
		}
    return l;
}
  • 11
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值