1.问题描述
题目0,1......n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。(来自《剑指offer》)
2.分析
1)用环形链表模拟圆圈,然后扫描链表删除结点,如果扫描到了链表结尾,重新在指向链表开头以此来模拟环形链表。
typedef struct node
{
int data;
struct node* next;
}ListNode;
int GetSize(ListNode* head)
{
if (head == NULL)
{
return 0;
}
int length = 0;
while (head != NULL)
{
head = head->next;
length++;
}
return length;
}
int LastRemainint(int m,ListNode* head) //直接传入了n个结点的链表
{
if (m < 1 || head == NULL)
{
return -1;
}
ListNode *start = head;
ListNode *record = NULL;
while (GetSize(head) > 1)
{
//找到要删除的结点
for (int i = 1; i < m; i++)
{
record = start;
start = start->next;
if (start == NULL) //代表record是尾结点,那么下个该删除的是头结点,头结点的record应该为null。
{
record = NULL;
start = head;
}
}
//删除结点 如果是头结点
if (record == NULL)
{
head = head->next;
start = head;
}
else
{
if (start->next == NULL)//如果删除的结点是尾结点,删除结点并在指向头结点,否则直接删除结点。
{
record ->next = NULL;
start = head;
}
else
{
record->next = start->next;
start = record->next;
}
}
}
return head->data;
}
2)分析每次被删除的数字的规律并直接计算出圆圈中最后剩下的数字
int LastRemaining(int n,int m)
{
if (m < 1 || n < 1)
{
return -1;
}
int last = 0;
for (int i = 2; i <= n; i++)
{
last = (last + m) % i;
}
return last;
}