1、数组删数

该代码实现了一个循环队列,通过每隔两个元素删除一个元素的规则,直至只剩下一个元素。程序首先初始化队列,然后不断更新指针,直至找到最后一个被删除的元素并输出其原始下标。

1.有一个数组a[N]顺序存放0~N-1,要求每隔两个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以8个数(N=7)为例:{0,1,2,3,4,5,6,7},0->1->2(删除)->3->4->5(删除)->6->7->0(删除),如此循环直到最后一个数被删除。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

#define ARRAY_SIZE  3

int get_cnt(int *a) 
{
    int cnt = 0;
    int i = 0;

    while(cnt < ARRAY_SIZE)
    {
        if(a[cnt] == 0)
        {   
            i++;
        }   
        cnt++;
    }   

    return i;
}

int get_next(int *array, int cur)
{
    int a = 3;
    int cnt=0, raw=0;
    raw = cur;
    while(a)
    {
        cur = (cur+1) % ARRAY_SIZE;
        if(array[cur] == 0)
        {
            a--;
        }
        else
        {
            cnt++;
            if(cnt > ARRAY_SIZE*3)
            {
                array[raw] = 1;
                return raw;
            }
        }
    }
    array[cur] = 1;
    return cur;
}

int main(int argc, char** argv)
{
    int a[ARRAY_SIZE] = {0};
    int i=ARRAY_SIZE-1, j=ARRAY_SIZE-1;

    do
    {
        j = i;
        i = get_next(a, j);
        printf("i=%d, j=%d, remain=%d\n", i, j, get_cnt(a));
    } while((i-j) || get_cnt(a)>=2);

    printf("%s(%d):final is %d\n", __FILE__, __LINE__, i);
    return 0;
}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <malloc.h>

int size  = 0;

int get_cnt(int *a) 
{
    int cnt = 0;
    int i = 0;

    while(cnt < size)
    {
        if(a[cnt] == 0)
        {   
            i++;
        }   
        cnt++;
    }   

    return i;
}

int get_next(int *array, int cur)
{
    int a = 3;
    int cnt=0, raw=0;
    raw = cur;
    while(a)
    {
        cur = (cur+1) % size;
        if(array[cur] == 0)
        {
            a--;
        }
        else
        {
            cnt++;
            if(cnt > size*3)
            {
                array[raw] = 1;
                return raw;
            }
        }
    }
    array[cur] = 1;
    return cur;
}

int main(int argc, char** argv)
{
    int *a;
    int i=0, j=0;
    
    scanf("%d", &size);
    if(size>999)
    {
        size = 999;
    }
    i = size-1;
    j = size-1;
    a = (int *)calloc(size, sizeof(int));
    
    do
    {
        j = i;
        i = get_next(a, j);
      //  printf("i=%d, j=%d, remain=%d\n", i, j, get_cnt(a));
    } while((i-j) || get_cnt(a)>=2);

   // printf("%s(%d):final is %d\n", __FILE__, __LINE__, i);
    printf("%d", i);
    free(a);
    return 0;
}

正确答案

#include "stdio.h"

typedef struct queue{
	struct queue *next;
	int val;
}QUEUE_S;

int main(void){
	int n, i;
	QUEUE_S q[1000], *p;

	while (scanf("%d", &n) != EOF){

		/* 初始化循环队列 */
		for (i = 0; i < n - 1; i++){
			q[i].val = i;
			q[i].next = &q[i + 1];
		}
		q[i].val = i;
		q[i].next = q;

		p = q;
		while (1){
			if (p == p->next){
				printf("%d\n", p->val);
				break;
			}
			p->next->next = p->next->next->next; /* 删除间隔两个之后的元素 */
			p = p->next->next; /* 更新指针位置 */
		}
	}
	return 0;
}
### 数组中指定字的实现方法 #### 1. 使用新数组存储结果 通过遍历原数组,将不等于指定字的元素存入新数组,最后返回新数组。这种方法不会修改原数组内容,适用于需要保留原数组的情况。 ```c // 移除数组 arr 中的所有值与 item 相等的元素。不要直接修改数组 arr,结果返回新的数组 function clearArrItem(arr, item) { var arrs = []; for (var i = 0; i < arr.length; i++) { if (arr[i] !== item) { arrs.push(arr[i]); } } return arrs; } var arrs = [1, 2, 5, 4, 2, 1, 5, 2, 1, 2, 5, 42, 1, 4, 11, 1, 1, 1, 1, 11]; console.log(clearArrItem(arrs, 1)); // 输出除后的新数组[^1] ``` #### 2. 原地除法 通过双指针技术,可以在原数组上进行操作,从而少空间复杂度。这种方法适合在内存有限的情况下使用。 ```c #include <stdio.h> int main() { int arr[] = {1, 2, 3, 4, 2, 5}; int sz = sizeof(arr) / sizeof(arr[0]); int del = 0; // 指定的字 scanf("%d", &del); int i = 0, j = 0; for (i = 0; i < sz; i++) { if (arr[i] != del) { arr[j++] = arr[i]; // 将非目标元素前移 } } printf("除后->"); for (i = 0; i < j; i++) { printf("%d ", arr[i]); } return 0; } ``` 上述代码通过双指针 `i` 和 `j` 实现了原地除指定字的功能[^4]。 #### 3. 使用覆盖法 当找到需要除的元素时,将其替换为数组末尾的元素,并缩短数组长度。这种方法可以避免频繁移动元素,从而提高效率。 ```java public static int removeElement(int[] nums, int val) { int length = nums.length; int i = 0; while (i < nums.length) { if (val == nums[i]) { --length; // 把当前元素放到最后 nums[i] = nums[nums.length - 1]; nums = Arrays.copyOf(nums, length); i = 0; // 重新从头开始检查 } else { ++i; } } System.out.println(Arrays.toString(nums)); return length; } ``` 此代码展示了如何通过覆盖法数组中的指定字[^3]。 #### 4. C++ 示例 在C++中,可以通过标准库函 `std::remove` 和 `erase` 方法实现类似功能。 ```cpp #include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> a = {3, 2, 2, 3}; int val = 3; a.erase(std::remove(a.begin(), a.end(), val), a.end()); for (int i = 0; i < a.size(); i++) { std::cout << a[i] << " "; } return 0; } ``` 这段代码利用了STL中的 `std::remove` 函除指定元素[^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值