12.28学习心得

题目描述

萝卜上次已经说过要给各位同学出一道冒泡排序,那么此题就以冒泡排序为主吧,可是实验室的学长学姐觉得学弟学妹们都很厉害,所以就加了各种各样的条件,最 终萝卜还是选择加一些条件,比如:让你直接排序输出结果就体现不出冒泡排序了。所以萝卜决定必须要用冒泡排序才能做出来的题目才叫冒泡排序的题目嘛?所以 这里只需要你在使用冒泡排序的时候统计交换的次数,在定义一个规则,如果存在相同的数,那么出现较早的那个数就排在后面。请帮萝卜解决这个问题吧。

输入

只有一组数据。

第一行一个n。(n<100)

接下来有n个数,表示要排序的数(不超过100)。

输出

输出交换的次数。

样例输入 

3
1 2 2

样例输出 

1

提示

相同的数出现早,即下标小的那个数。

比如样例:

数字1 2 2

下标0 1 2

这个题目好坑,本来以为是道简简单单的冒泡,随便一写就是一个答案错误,然后写了半天都出不来只能又去参考别人家的代码了:https://blog.csdn.net/qq_43506138/article/details/84027568?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167222811516800213082288%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167222811516800213082288&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-84027568-null-null.142^v68^js_top,201^v4^add_ask,213^v2^t3_esquery_v3&utm_term=%E8%90%9D%E5%8D%9C%E7%9A%84%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F&spm=1018.2226.3001.4187

#include"stdio.h"
int main()
{
    int n,a[101],i,j,m,t,q;
    scanf("%d",&n);
    {
        m=0;
        for(i=0; i<n; i++)
            scanf("%d",&a[i]);
        for(i=n-1; i>0; i--)
            for(j=0; j<i; j++)
            {
                if(a[j]>a[j+1])
                {
                    t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=t;
                    m++;
                }


            }
       
        q=1;
        j=0;
        while(j!=n-1)
        {
            for(q=1; j<n-1; j++)
                if(a[j]==a[j+1])
                {
                    q++;
                }
                else
                {
                    j++;
                    break;
                }
            while(q--)
            {
                m=m+q;
            }
        }
    }

    printf("%d\n",m);
}


其实这个题目吧有个小毛病:它没有说明是按什么顺序排的,从大到小还是从小到大,但我们还是得硬着头皮上:

来解释一下冒泡排序后的,有个循环条件是j!=n-1,然后循环里面的就是在一个循环里当a[j]和a[j+1] 相等的时候让q加加否则就j++且break;画个图就明白了:

这里搞错了,m在不相等的时候加的是0; 

 

在这里加上几句棕色的话:为了让while的条件不小于零(对于--q),或者是让m不至于反而减了一个数 。

这里小小再总结一下,我认为自己之所以错了这个题目,是没有理解透彻冒泡排序的原理,而只是把它当作一种方法来理解,emmm所以,学算法不应该只是单纯的去学模型应该还要去理解它,而自己模拟是最好的方式。 

13号又是星期五是一个不寻常的日子吗? 13号在星期五比在其他日少吗?为了回答这个问题,写一个程序来计算在n年里13 日落在星期一,星期二......星期日的次数.这个测试从1900年1月1日到 1900+n-1年12月31日.n是一个非负数且不大于400. 这里有一些你要知道的: 1900年1月1日是星期一. 4,6,11和9月有30天.其他月份除了2月有31天.闰年2月有29天,平年2月有28天. 年份可以被4整除的为闰年(1992=4*498 所以 1992年是闰年,但是1990年不是闰年) 以上规则不适合于世纪年.可以被400整除的世纪年为闰年,否则为平年.所以,1700,1800,1900和2100年是平年,而2000年是闰年. 请不要预先算好数据!

输入

一个整数n.

输出

七个在一行且相分开的整数,它们代表13日是星期六,星期日,星期一.....星期五的次数.

样例输入 复制

20

样例输出 复制

36 33 34 33 35 35 34

要说这个题我写了多久的话,嗯,我自己都不记得,从根本没思路,到有思路但看错了题,再到认真看题后认真打代码,我都没写出来,为什么我会如此执着呢?大概是那个题的正确率真的很高,不甘心,但最后只能学别人的代码了。哭死! 

来看看代码,嗯,我模仿的是这个作者的链接和代码

https://blog.csdn.net/weixin_73048230/article/details/128448650

代码,我自己写的和原作者的没很大区别,这里附上原作者的代码

#include <stdio.h>
 
int fun(int year,int month)
{
	int days=0,i;
	if(year>1900)
	{
		for(i=1900;i<year;i++)
		{
			if(i%400==0 || i%4==0 && i%100!=0)
				days+=366;
			else days+=365;
		}
	}
	else days+=0;
	if(month>=2)
	{
		for(i=1;i<month;i++)
		{
			if(i==4 || i==6 || i==9 || i==11)
				days+=30;
			else if(i==2)
			{
				if(year%400==0 || year%100!=0 && year%4==0)
					days+=29;
				else days+=28;
			}
			else days+=31;
		}
	}
	days+=13-1;
	return days;
}
 
int main()
{
	int n,i,j,m,t,k;
	int a[7]={0};
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=12;j++)
		{
			m=fun(1900+i-1,j);
			t=m%7;
			for(k=0;k<7;k++)
			{
				if(t==k)
				{
					a[(1+k)%7]++;
					break;
				}
			}
		}
	}
	printf("%d",a[6]);
	for(i=0;i<=5;i++)
		printf(" %d",a[i]);
	return 0;
}

然后我在这细细解读一下:

首先它是定义了一个函数,我们来看这个函数里面的部分,让一个变量days先赋值为零,并且在年份大于1900年的时候进入一个循环循环里面判断是闰年就让日子加上366(闰年比平年多一天)然后else days+=0;的意思是如果没有大于1900年就是days本身,也就是说,那是因为作者是从1900年开始算,分年月算,如果把1900算在里面那不就多算了一个年份不,而之所以不全按年份算是因为题目给的月份有差,如果全按年份算容易出错,往下面看就会更通透;下面判断如果月大于等于2的话就进入条件,月份从一开始,注意这里面有一个嵌套的条件语句,大概就是判断大小月和二月,结束条件后,又有一个这样的语句,days+=13-1;这是要干嘛的?和上面有什么关系?因为我们要求的的这个就是从13号开始算的,而减一是因为从一号开始的到十三号因为在月份里面正经的0号是在月末,其实从这里我就可以大致推断出这个函数是干嘛的了,无非是求日子天数;接着我们可以看主函数,更清晰明了,两个嵌套循环,一个是年一个是月,再调用函数并传年份形参和月份形参,然后用t短暂存日子对7天的周期取余,而进来循环可能就有人迷了?为什么要加一,为什么还要对7取余?别忘了我们是从星期六开始的,加个一不就是星期天也就是七吗?而对七取余这里其实是达到了一个让星期天的序号成为首号元素,你可以想想。而这个break就起到了节省时间的作用,毕竟只有一个k与t对应,找到就立马结束不是节省了很多时间吗?下面的代码就不说了。这里来提一嘴为什么不一个月一个月的求是星期几的个数呢?不要把数字算那么大,但是要知道,你每个月对应的13的星期几可能是会变的,那时候你怎么控制呢?这种题对于我这种边界干不怎么强的人就真的很难,所以还是得多刷题。

最最最后,当然少不了自己的激动人心的环节啦,捡回那颗炽热的心:谁的青春不是兵荒马乱,我们也是自己的太阳。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值