求最右边的第一个1的数组

求一个字节(8位)表示的数字中查找最右边第一个非0的数字的位置,该数组如何解析呢?

static const uint8 rightmost_one_pos[256] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

解析:此数组对应了8位,也就是一个字节的数字对应的最右边非0的第一个bit的位置。
对应数组【0~7】位。
假如:00000000,没有最右边的,对应数组组下标为0
00000001,最右边非0为第1个数,对应数组下标为1
00000010,最右边非0为第2个数, 对应数组下标为2
00000011,最有表非0为第1个数,对应数组下标为3
00000100,最右边非0为第3个数,对应数组下标为4
……
可以看出来,数组中下标对应的数字比我们计算的小1。
会在后来讲解。
所以,此数组中保存的数字,使我们计算的最右边非0的数字的结果。

要在一个数组到第k小的元素,你可以使用一种叫做“快速选择”(QuickSelect)的算法,它是快速排序算法的一个变种,用于查中位或指定位置的元素。这种方法的时间复杂度通常是O(n),在最坏情况下是O(n^2)但这种情况常罕见。 以下是一个简单的快速选择算法的伪代码实现: ```c // 快速选择函 int quickSelect(int arr[], int left, int right, int k) { if (left == right) // 如果只有一个元素,直接返回 return arr[left]; // 基准值的选择,这里通常随机选取 int pivotIndex = partition(arr, left, right); // 如果基准值的位置就是我们要的k,直接返回 if (pivotIndex == k - 1) return arr[pivotIndex]; else if (pivotIndex < k - 1) // 第k个元素在基准值右边,递归右半部分 return quickSelect(arr, pivotIndex + 1, right, k); else // 第k个元素在基准值左边,递归左半部分 return quickSelect(arr, left, pivotIndex - 1, k); } // 分区函,返回基准值的新位置 int partition(int arr[], int left, int right) { int pivot = arr[right]; // 常用最后一个元素作为基准值 int i = left - 1; for (int j = left; j < right; j++) { if (arr[j] <= pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[right]); // 将基准值放到正确的位置 return i + 1; } ``` 使用这个函,你可以像下面这样调用它来出第k小的元素: ```c int main() { int arr[] = {5, 8, 2, 6, 9, 1}; // 示例数组 int n = sizeof(arr) / sizeof(arr[0]); int k = 3; // 指定查第3小的元素 int result = quickSelect(arr, 0, n - 1, k - 1); // 注意k-1是因为数组索引从0开始 printf("The %dth smallest number in the array is %d\n", k, result); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值