类和对象-常见OJ题

Ⅰ、求1+2+3……+n

描述如下:

求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

数据范围: 0<<n≤200
进阶: 空间复杂度 )O(1) ,时间复杂度 O(n)

单看题目会十分的简单,但是这道题目是有要求的!!不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

思路:我们前面已经知道:一个对象在创建的时候,会自动的去调用它的默认构造函数,那么我们可以创建一个专门用来求和的类,然后在解决类里面创建n个求和类对象,那么就可以调用n次求和构造函数,是不是就可以很好的解决?

        但是呢,这里有个问题就是,我们每次加上的数都比上一个数大,就是会用到上一次的结果,所以我们可以借助静态成员变量,在类中声明,为什么不能用普通的成员变量呢?就是因为对象里面存的自己的成员变量,n次调用的话,并不是同一个增量,而静态成员变量是属于整个类的,不属于任何一个对象,这就保证n次调用,改变的都是同一个增量!!

核心思路就两点:

充分利用C++特性,构造对象构造函数会自动调用的特点,让求和在构造函数中进行完成

②由于所有对象要针对相同的和进行更新,所以其成员定义为static

class Sum
{
public:
    Sum()
    {
        _sum+=_i;
        _i++;
    }
    static int GetSum()
    {
        return _sum;
    }
private:
    static int _i;
    static int _sum;
};
int Sum::_i=1;
int Sum::_sum=0;


class Solution {
public:
    int Sum_Solution(int n) {
        Sum a[n];//C99支持变长数组,这里也可以使用new来开空间
        return Sum::GetSum();
    }
};

当然了,还有一种写法就是将Sum类写在Solution里面,把它当作内部类,这样可以利用内部类天生就是外部类的友元类这一特性,去访问外部类的私有成员

class Solution {
public:
    class Sum
    {
    public:
        Sum()
        {
            _sum+=_i;
            _i++;
        }
    };
    int Sum_Solution(int n) {
        Sum a[n];
        return _sum;
    }
private:
    static int _i;
    static int _sum;
};
int Solution::_i=1;
int Solution::_sum=0;

这样的写法就少写了静态成员函数去获取静态成员变量这一步骤,当然了,你也可以把静态成员变量的权限设置为公有,这样你也可以不用写静态成员函数!

Ⅱ、日期累加

描述:

设计一个程序能计算一个日期加上若干天后是什么日期。

输入描述:

输入第一行表示样例个数m,接下来m行每行四个整数分别表示年月日和累加的天数。

输出描述:

输出m行,每行按yyyy-mm-dd的个数输出。

示例:

输入:20110412

           20110422

输出:11

思路:大体思路就是,先将天数加到“日”上,判断是否符合大于月份的天数,如果大于,那就月向上加;如果加到当月份大于12时,那就年份向上加,如此循环就能够解决问题!特别注意闰年的情况!

#include <iostream>
using namespace std;
bool IsLeapYear(int year)
{
    return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}

int main()
{
    int m, n, year, month, day;
    cin >> m;
    int i = 0;
    int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//13是为了和月份对象
    while (i < m)
    {
        cin >> year >> month >> day >> n;
        if (IsLeapYear(year))
        {
            monthday[2] = 29;//判断闰年
        }

        //先把天数加上
        day += n;
        while (day > monthday[month])
        {
            day -= monthday[month];
            month++;
            if (month == 13)
            {
                year++;
                month = 1;
                if (IsLeapYear(year))
                {
                    monthday[2] = 29;
                }
                else
                {
                    monthday[2] = 28;
                }
            }
        }
        printf("%d-%02d-%02d\n", year, month, day);

        ++i;
    }
    return 0;
}

Ⅲ、日期差值

描述

有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。

输入描述:

有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD

输出描述:

每组数据输出一行,即日期差值

示例:

输入:

           20110412

           20110422

输出:11

思路一:比较两个日期的大小,找出大的日期,循环让大的日期减到和小的日期的年月相同为止,这就可以得到年相差的天数;然后在得到的天数上加上“日”相差的天数,最后还要注意题目说的:两个日期是连续的我们规定他们之间的天数为两天。说明要在结果上在加1才是最终结果

int GetMonthDay(int year, int month)//获取每月的天数
{
    int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
    {
        return 29;
    }
    return monthday[month];
}

bool Max(int y1, int m1, int d1, int y2, int m2, int d2)//找最大日期
{
    if (y1 > y2)
    {
        return true;
    }
    else if (y1 == y2)
    {
        if (m1 > m2)
        {
            return true;
        }
        else if (m1 == m2)
        {
            if (d1 > d2)
            {
                return true;
            }
        }
    }
    return false;
}
void Swap(int& x, int& y)//保证第一个日期是大的
{
    int tmp = x;
    x = y;
    y = tmp;
}
int main()
{
    int year1, month1, day1, year2, month2, day2;
    while (scanf("%04d%02d%02d\n%04d%02d%02d", &year1, &month1, &day1, &year2, &month2, &day2) != EOF)
    {
        //比较两个日期的大小,保证第一个日期最大
        if (!Max(year1, month1, day1, year2, month2, day2))
        {
            Swap(year1, year2);
            Swap(month1, month2);
            Swap(day1, day2);
        }

        int sum = 0;//记录差值
        while (!((year1 == year2) && (month1 == month2)))//大的减到与小的相同为止,记录年相差的天数
        {
            month1--;
            if (month1 == 0)
            {
                month1 = 12;
                year1--;
            }
            sum += GetMonthDay(year1, month1);//大的和小的年月相差的天数
        }

        int d = day1 - day2; //日之间的差值
        sum += d;//日累加到年差值上
        sum++;//最后结果在加1
        cout << sum << endl;
    }
    return 0;
}

思路二:①分别求出每个日期与0000年0月1日相差的天数。②再用两个距离天数相减就可以!③最后结果再加1

#include <iostream>
using namespace std;

 //平年从1月到n月的天数
  int mon[12]={0,31,59,90,120,151,181,212,243,273,304,334};

  //给出年月日,计算距离0000年0月1日的天数和
  int CountDay(int y,int m,int d)
  {
    // 计算0-y年的天数
    int yearDay = y*365+y/4-y/100+y/400;//这里面就包含闰年的天数

    // 计算到0-m月的天数
    int monthDay = mon[m-1];

    if(m > 2 && ((y%4 == 0 && y%100 != 0) || y%400==0))//闰年
      monthDay += 1;
    return yearDay + monthDay + d;
  }

  int main()
  {
    int year1,month1,day1;
    scanf("%4d%2d%2d",&year1,&month1,&day1);
    int n1 = CountDay(year1,month1,day1);

    int year2,month2,day2;
    scanf("%4d%2d%2d",&year2,&month2,&day2);
    int n2 = CountDay(year2,month2,day2);

    cout<<abs(n1-n2)+1<<endl;

  }

Ⅳ、计算日期到天数的转化

描述

根据输入的日期,计算是这一年的第几天。保证年份为4位数且日期合法。

进阶:时间复杂度:O(n) ,空间复杂度: O(1) 

输入描述:

输入一行,每行空格分割,分别是年,月,日

输出描述:

输出是这一年的第几天

示例:

输入:2012 12 31

输出:366

思路:可先用一个数组将天数先存起来(可以先按照平年计算),然后再判断日期是否为3月以上,因为只有这时才需要去判断是否为闰年,如果是3月以上并且是闰年,那需要在总天数上加1即可!

#include <iostream>
using namespace std;

int main() 
{
    int year,month,day;
    cin>>year>>month>>day;

    int dayarr[13]={0,31,59,90,120,151,181,212,243,273,304,334,365};//平年
    int totalday=dayarr[month-1]+day;//总天数
    //下标-1可以这样理解:比如现在是二月1日,那是一年的第几天?,肯定是前面1月的总天数
    //所以下面需要判断是否是3月及以上,才需要判断是否为闰年
    if((month>2)&&((year%4==0&&year%100!=0)||year%400==0))
    {
        totalday+=1;
    }
    cout<<totalday<<endl;
}

Ⅴ、打印日期

描述

给出年分m和一年中的第n天,算出第n天是几月几号。

输入描述:

输入包括两个整数y(1<=y<=3000),n(1<=n<=366)。

输出描述:

可能有多组测试数据,对于每组数据, 按 yyyy-mm-dd的格式将输入中对应的日期打印出来。

示例:

输入:

2000 3

2000 31

2000 40

2000 60

2000 61

2001 60

输出:

2000-01-03

2000-01-31

2000-02-09

2000-02-29

2000-03-01

2001-03-01

思路:相对简单,只需要去判断输入的天数是否符号当前月的天数即可,如果大于,那就月向上加!有点像上面日期累加!

#include <iostream>
using namespace std;
int main()
{
    int year, day, month;
    int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//先算平年
  
    while (cin >> year >> day)
    {
        int month = 1;
        if ((year%4==0 && year%100!=0)||(year%400==0))
        {
            monthday[2] +=1 ;//闰年2月加上1
        }

        //判断输入的天数是否符合当前月的天数,大于就月向上加
        while (day > monthday[month])
        {
            day -= monthday[month];
            month++;
        }

        printf("%d-%02d-%02d\n", year, month, day);
    }
    return 0;
}

小贴士:上面的题目大家可以点击!!

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值