一组顺序数字 1~10,依123 123 循环数数,每遇到3的位置移除该位置数,重新123继续数;
直至剩余一个数,问该数是多少?
同事提起的一个问题,思考之后使用C语言实现了下,代码如下:
#include <stdlib.h>
#include <stdio.h>
//定义一个数据结构 用于创建链表的结点
typedef struct list{
int num; //结点值
struct list * next; //结点指向下一个结点的指针
}List;
//*创建循环链表 接收链表长度 返回头结点指针
List * create(int n){
List * head; //头结点 指针
List * p1; //当前结点的前一结点 指针
List * p2; //当前结点 指针
int i; //变量i 用于指示循环;同时也用作后续结点的num值(便于理解)
//为头结点 动态分配其数据类型大的空间 返回指针 赋值给head指针;出错则打印error
if ((head = (List *)malloc(sizeof(List))) == NULL) {
printf("Error");
return NULL;
}
//为头结点赋值:将头结点的next指针置空,num设置为链表长度
head->next = NULL;
head->num = n;
//循环添加头结点之后的后续结点
for (i= 1; i < n + 1; i++) {
//动态分配结点 赋值给临时变量 指针p
List * p=(List *)malloc(sizeof(List));
//p num字段赋值为i的值(对应一个数字)
p->num = i;
if (head->next == NULL) {
//将后续结点连入链表头结点(只连入一次)
head->next = p;
p1 = head; //更新当前结点的前一结点 指针
p2 = p; //更新当前结点 指针
}else{
p1 = p2; //更新当前结点的前一结点 指针
p2->next = p; //将新创建结点 连入链表
p2 = p; //更新当前结点 指针
}
}
p2->next = head->next;//将链表 首尾链接 形成循环
//返回头结点指针
return head;
}
//*操作循环链表 将对应数数3的位置结点跳过 重新数数 直至链表剩余一个结点 返回该结点指针
//*接收参数:链表头结点指针 链表长度
List * lastOne(List * table,int lenth){
//判断链表是否为空
if (table->next == NULL) {
return NULL;
}
//判断链表是否只有一个结点 若只有一个结点 返回其指针即可
if (table->next->next == NULL) {
return table->next;
}
List * beforEnd = table; //当前结点的前一结点指针
List * end = table->next; //当前结点指针
int i = 0; //变量 表示1-3循环
int count = 0; //循环条件:长度为length的链表 最多只需要循环遍历处理length-1次 最后保留1个数
while (count < lenth - 1) {
i++;//表示位置 从1开始
if (i%3 == 0) {
//位置数数至3 则对应位置的结点需要移除 用p表示
List * p = end;
printf("对应下标3的位置:需要移除的数是%d\n",p->num);
//链表重新连接
beforEnd->next = end->next;
//更新当前结点指针(当前结点的前一结点指针不变)
end = end->next;
//释放移除的结点内存
if (p != NULL) {
free(p);
count ++;//处理次数 用作循环条件
}
i = 0;//位置标识置0
}else{
//继续遍历
printf("对应下标%d的位置:数字=%d\n",i,end->num);
beforEnd = end; //更新当前结点的前一结点指针
end = end->next;//更新当前结点指针
}
}
printf("最后剩余的数字=%d\n",end->num);
//返回最终剩余的一个结点
return end;
}
int main() {
//定义链表长度
int num = 10;
//创建循环链表 返回链表头结点
List * start = create(num);
//测试 循环打印链表 我们可以打印2*num次
List * p = start->next;
int i =0;
while (p && i<(num*2)) {
printf("%d\n",p->num);
p = p->next;
i++;
}
//操作循环链表
List * point = lastOne(start,num);
//释放最终链表中剩余的一个结点
if (point != NULL) {
free(point);
}
//释放链表头结点
if (start != NULL) {
free(start);
}
return 0;
}
C语言的部分也不太熟悉了,代码实现不是很简洁,希望和大家交流,学习更简洁易懂的处理;
log如下:
./linkedlist
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
对应下标1的位置:数字=1
对应下标2的位置:数字=2
对应下标3的位置:需要移除的数是3
对应下标1的位置:数字=4
对应下标2的位置:数字=5
对应下标3的位置:需要移除的数是6
对应下标1的位置:数字=7
对应下标2的位置:数字=8
对应下标3的位置:需要移除的数是9
对应下标1的位置:数字=10
对应下标2的位置:数字=1
对应下标3的位置:需要移除的数是2
对应下标1的位置:数字=4
对应下标2的位置:数字=5
对应下标3的位置:需要移除的数是7
对应下标1的位置:数字=8
对应下标2的位置:数字=10
对应下标3的位置:需要移除的数是1
对应下标1的位置:数字=4
对应下标2的位置:数字=5
对应下标3的位置:需要移除的数是8
对应下标1的位置:数字=10
对应下标2的位置:数字=4
对应下标3的位置:需要移除的数是5
对应下标1的位置:数字=10
对应下标2的位置:数字=4
对应下标3的位置:需要移除的数是10
最后剩余的数字=4