2thweek.training.c。链表典型题

题意:

某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。

Input

本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。

Sample Input

2 20 40

Output

共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。

分析及思路:

一开始是直接用的链表解决,将士兵人数为1、2的情况单列出来。士兵数大于三时用其编号除以二,编号恰能整除2的元素剔除出链表,判断一次士兵人数是否不小于三。如果是接着将重新组成的链表的编号能整除3的元素剔除,然后再次判断新的链表的元素人数是否不小于三。。。。。。

可是由于对链表和迭代器应用不熟悉,程序怎么改都输不出案列答案。

失败代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<list>
 4 #include<algorithm>
 5 using namespace std;
 6 int main()
 7 {
 8     int N,i;
 9     scanf("%d",&N);
10     while(N--)
11     {
12         int n;
13         list<int>a;
14         while(scanf("%d",&n)==1 && n<=5000)
15         {
16
17         for(i=1;i<=n;i++)
18         {
19
20             a.push_back(i);
21
22
23         }
24         }
25
26
27         list<int>::iterator it,ip;
28         int s=a.size();
29         while(s==1||s==2)
30         {
31             printf("%d",a.front());
32         }
33
34        while(s>=3)
35        {
36            for(it=a.begin();it!=a.end();  )
37             {
38                 if((*it)%2==0)
39                 {
40                    //ip=it;
41                    a.erase(it);
42                    it++;
43                    s--;
44                 }
45             else  ip=it;
46             }
47
48        }
49        while(s>=3)
50        {
51                 for(it=a.begin();it!=a.end(); )
52                 {
53                     if((*it)%3==0)
54                     {   // ip=it;
55                         a.erase(it);
56                         it++;
57                         s--;
58                     }
59                      else  ip=it;
60                 }
61
62
63        }
64
65
66        for(it=a.begin();it!=a.end();it++)
67
68         //if(it==a.end())
69         //printf("%d",a.end());
70        //else
71         printf("%d ",(*it));
72
73        printf("%d",a.end());
74     }
75
76        return 0;
77 }

代码留此目的是为了再次过来修改,以待重新用链表的方法完成。

当时参考了大神的代码和旁边的童鞋的意见,觉得直接用模拟也方便。代码如下:

 1 #include<stdio.h>
 2 #include<algorithm>
 3 using namespace std;
 4 int main()
 5 {
 6     int a[5002];
 7     int t,n,m;
 8     int i,j,k;
 9     scanf("%d",&t);
10     while(t--)
11     {
12         scanf("%d",&n);
13         for(i=0;i<n;i++)    //存储士兵编号
14             a[i]=i+1;
15         m=n;
16         k=0;
17         while(m>3)  //人数大于3,继续报数删人
18         {
19             j=0;
20             k=0;
21             for(i=0;i<m;i++)
22             {
23                 j++;
24                 if(j==2)    //报数为2,士兵出列
25                 {
26                     a[i]=5004;  //出列者编号设为最大值,排序后直接屏蔽,避免下次搜索超时 觉得这样简直忒好,不是真的直接剔除元素,                                  //     也就无需考虑后面的删除第三个人的序号问题
27                     j=0;
28                     k++;   //k为出列人数
29                 }
30             }
31            sort(a,a+m);        //     一轮报数完成,士兵排序站队,屏蔽已报数士兵
32             m-=k;
33             j=0;
34             if(m<=3)        //    人数不大于3,停止报数删人
35                 break;
36             k=0;
37             for(i=0;i<m;i++)
38             {
39                 j++;
40                 if(j==3)
41                 {
42                     a[i]=5004;
43                     j=0;
44                     k++;
45                 }
46             }
47             sort(a,a+m);    //一轮报数完成,士兵排序站队,屏蔽已报数士兵
48             m-=k;
49         }
50         printf("%d",a[0]);
51         for(i=1;i<m;i++)
52             printf(" %d",a[i]);
53         puts("");
54     }
55     return 0;
56 }

小抱怨:对于链表队列真是把我愁了,有点分不清楚。只好拿着大神的代码模仿又模仿。等搞清楚定要回头重写一番。大家都很厉害真的很是沮丧。学姐告诉我:全世界的光明也不能剥夺一支小蜡烛发亮的权利,全世界的黑暗也不能一支小蜡烛失去光辉!   或许自己的进步微不足道也不要轻易放弃,要知道未来真的在路上在手上在不断运转的大脑里。

时间: 2024-10-13 11:48:33

2thweek.training.c。链表典型题的相关文章

数学,位运算,典型题

数学,自然想到组合数,逆元,阶乘 先来一发组合数相关, #define MAXN 200001 const int mod=1000000007; typedef long long ll; int n,m,r,c; ll ans,s; ll inv[MAXN],fac[MAXN],dev[MAXN]; //inv[]逆元,fac[]阶乘,dev[]阶乘的逆元 void chuli(int x) { inv[1]=1; fac[1]=1; dev[1]=1; fac[0]=1; dev[0]=1

链表十题(本节终)

本节内容汇总了近期所做的有关于链表的10道题目,以超链接的形式在下面,点击便可以跳转相应的博文. 由于个人水平有限,所分享的十题都是leetcode网站上简单.中等难度的题目,每道题目都采用java和C语言来进行答题的,并且大多数题目都提供了2种及以上的不同思路. 由于打字困难,对于题目的解答思路都在代码的注释中.该十大题目大部分都不是最优解法,仅是作者的个人想法的体现,仅供参考.如果读者也有着自己对题目的想法,欢迎将您的答案留在评论区,充实本文内容,一起探究算法题的乐趣. 1.回文链表 2.旋

(诡异Floyd&amp;自环)MZ Training 2014 #15 E题(POJ 2240)

你们见过这么诡异的FLOYD吗? 先上题. [Description] 货币的汇率存在差异,例如,假设1美元购买0.5英镑,1英镑买10法郎,而1法国法郎买0.21美元.然后,通过转换货币,一个聪明的交易者可以从1美元买0.5 * 10 * 0.21 = 1.05美元,获利5%. 你的任务是写一个程序,以一个货币汇率列表的作为输入,然后确定能不能获利. [Intput] 输入包含多组测试数据,每组数据第一行一个数n(1<=n<=30),表示有n中货币,接下来n行,每行一种货币名称,名称内不会出

链表刷题总结

* class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } 查找一个链表的中间节点:使用快慢指针 注意:如果用途是对链表的左右分别递归调用时,需要将中间节点的前一个结点的next = null  即需要一个pre结点(注意先要赋null初始化) ListNode midList(ListNode node){ if(node == null || node

LeetCode141-环形链表(水题)

因为链表最后一个元素都是null,只有能到达null的,就是无环. 有环链表,只要两个不同的指针,一个走一步,一个走两步,绝对能相遇. 证明一下为什么可以相遇. 假设A的速度是1次一步,B的速度是2步,链表有环,且长度是N. 假设在X步之后相遇了,间隔是D圈 那么就是X/N+DN = 2X/N 可以求得相遇的步数为X=DN*N. 其实给定一个假设更好理解. 如果能求出在某个时刻他们位置一样,那肯定能证明能相遇,用跑操场做类比. 第一次相遇,肯定是他们之间差了一圈.因为刚好一圈的距离才会第一次相遇

链表-常见题(二)

回文链表: 1.首先快慢指针获取中间节点 2.利用栈存储后半段节点值 或者反转后半段 3.前半部分链表与栈进行值比较,出现不等则表示非回文链表 合并两个有序链表: 1.空表检查 2.新建表头 3.表1和表2进行对比,逐个插入到表头 4.返回链表头节点 原文地址:https://www.cnblogs.com/hzk-note/p/9589071.html

反转链表算法题

反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶:你可以迭代或递归地反转链表.你能否用两种方法解决这道题? 解决方案 方法一:迭代 假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3. 在遍历列表时,将当前节点的 next 指针改为指向前一个元素.由于节点没有引用其上一个节点,因此必须事先存储其前一个元素.在更改引用之前,还需要另一个

链表算法题

单链表 function LinkedList() { //需要插入链表的元素 var Node = function(element) { this.element = element;//元素的值 this.next = null;//指向下一个节点项的指针 }; var length = 0;//链表的长度 var head = null;//链表中第一个节点(的引用) //向链表尾部追加元素 this.append = function(element) { var node = new

leetcode链表算法题实现思路

找出两个链表的交点(leetcode160) 一条链表遍历完之后跳转到下一条链表的头节点继续遍历.  因为当两条链表均被遍历一遍以后,第二次遍历时会同时到达节点相等的地方.如果没有相交的节点,两条链表均遍历两遍后,同时等于null,故返回null. public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode l1 = headA, l2 = headB; while (l1 != l2) { l1