C++算法(一)

༺ 个人主页 · 纪念229 ༻

🏠我的博客主页🏠

༒专栏目录:《数据结构》༒

༒专栏目录:《算法》༒

༒专栏目录:《C++》༒

༒专栏目录:《MySQL数据库》༒

༒专栏目录:《前端开发》༒

༒其它有趣的计算机知识༒

༺世上本没有路,走的人多了自然就有了༻


本文讲的是一些有关C++的一些算法题,希望对你有所帮助

题目链接:

计算日期到天数转换

日期差值

求1+2+3+...+n

打印日期

以后写的算法文章一般也用C++


文章目录


1.计算日期到天数转换

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<cassert>
using namespace std;
class Date {
  public:
    friend istream& operator>>(istream& in, Date& d);
    int GetMonthDay(int year, int month) {
        //这里判断的是传入的month不是类里的_month
        //里面的代码与类变量无关,与传入的year、month有关
        assert(month > 0 && month < 13);
        int a[13] = { -1, 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;
        } else {
            return a[month];
        }
    }



    int _year;
    int _month;
    int _day;
};
istream& operator>>(istream& in, Date& d) {
    in >> d._year >> d._month >> d._day;
    return in;
}


int GetYearDay(Date d) {
    int sum = 0;
    //这里的d._month--可以直接减减因为d._month是int类型可以直接调用
    /* for (int i =d._month; d._month ; d._month--) {
         sum += d.GetMonthDay(d._year, d._month);
     }*/
    //上面写法是错的因为不能记满一月的天数而错误的记了该月所有的天数(我们因该记该月过了的天数)
    for (int i = 1; i < d._month; i++) {
        sum += d.GetMonthDay(d._year, i);
    }
    sum += d._day;
    return sum;
}
int main() {
    Date d1;
    //写了友元函数就可以直接
    //cin >> d1,不用cin >> d1._year >> d1._month >> d1._day这么些
    cin >> d1;
    int sum = GetYearDay(d1);
    cout << sum << endl;
    return 0;
    //还有就是看到终端光标一闪一闪不是崩溃是在等待输入数据
}

这里我有一步没写好

friend istream& operator>>(istream& in, Date& d);

cin >> d1;

这里我利用友元函数和运算符重载来实现类的输入

没变要,直接写三个整型变量再给类实例化即可

有关Date的题目我们一般可以先把类Date基本需求写好

用得上

c 复制代码
class Date {
  public:
    friend istream& operator>>(istream& in, Date& d);
    int GetMonthDay(int year, int month) {
        //这里判断的是传入的month不是类里的_month
        //里面的代码与类变量无关,与传入的year、month有关
        assert(month > 0 && month < 13);
        int a[13] = { -1, 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;
        } else {
            return a[month];
        }
    }


 
    int _year;
    int _month;
    int _day;
};

friend istream& operator>>(istream& in, Date& d);

这一行可以不写利用类的实例化调用构造函数即可

这里面就一个要讲的DetMonthDay里面用的是传入的实参

不是_year、_month

因为调用_month是不会变的在不调用其它成员函数的情况下

会导致得到的月天数永远不变

判断闰年的地方注意括号的使用,还有就是返回29天的条件是

month == 2 && 闰年 不是 month = 2 && 闰年 后面那个是赋值

来到取该日期所在年份的总天数

int sum = GetYearDay(d1);

c 复制代码
int GetYearDay(Date d) {
    int sum = 0;
    //这里的d._month--可以直接减减因为d._month是int类型可以直接调用
    /* for (int i =d._month; d._month ; d._month--) {
         sum += d.GetMonthDay(d._year, d._month);
     }*/
    //上面写法是错的因为不能记满一月的天数而错误的记了该月所有的天数(我们因该记该月过了的天数)
    for (int i = 1; i < d._month; i++) {
        sum += d.GetMonthDay(d._year, i);
    }
    sum += d._day;
    return sum;
}

思路就是将过完的月份天数和该月过完的天数加起来就是该日期所在年份的总天数

我们先记完过完的月份天数

然后将剩余天数加起来即可

这个是我写的一个错误写法没记一月的天数将最后一月的天数记上了

复制代码
 //这里的d._month--可以直接减减因为d._month是int类型可以直接调用
    /* for (int i =d._month; d._month ; d._month--) {
         sum += d.GetMonthDay(d._year, d._month);
     }*/
    //上面写法是错的因为不能记满一月的天数而错误的记了该月所有的天数(我们因该记该月过了的天数)

应该从1开始遍历,最后月天数不计最后加上剩余天数

复制代码
for (int i = 1; i < d._month; i++) {
        sum += d.GetMonthDay(d._year, i);
    }
    sum += d._day;

2.日期差值

写到这这里我就以为和上一题差不多,但是做题是我们一定要看完题

这里是多组输入要用到while循环

还有就是这里传入的不是六个变量来输入年月日而是

传入两个连起来的整型日期

由此我们得出得到的值会很大我们要设置一些long long 类型的变量

描述

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

这个的意思就是日期差值是两个天数算出来加1其实就是等差数列

c 复制代码
//这题算的是年月日所有的天数之差(两天数之差加一才是日期差值)
#include<iostream>
using namespace std;

bool isleap(int y)
{
    return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}

int dm[13] = { 0 ,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
long long calc(int y, int m, int d)
{
    long long days = 0;
    // 先算年一共有多少天
    //这里i = y - 1,第y年全年不算该年月日后面会补
    for (int i = y - 1; i > 0; i--) days += isleap(i) ? 366 : 365;
    //再算月一共有多少天
    for (int i = 1; i < m; i++)
    {
        days += dm[i];
        //这里是i == 2不是m == 2
        if (i == 2 && isleap(y)) days++;
    }
    //最后返回 天数加剩余的天数
    return days + d;
}

int main()
{
    int a, b;
    while (cin >> a >> b)
    {
        int y1 = a / 10000, m1 = a / 100 % 100, d1 = a % 100;
        //这里用的是b不是a
        int y2 = b / 10000, m2 = b / 100 % 100, d2 = b % 100;
        //想取数字中的3、4位先/ 100 再 % 100
        long long diff = calc(y1, m1, d1) - calc(y2, m2, d2);
        //取值和函数返回值都取long long是因为转化数据太大
        //最后要求打印的值为整数
        if (diff < 0) diff = -diff;
        //日期差值为 diff + 1
        //最后是<<endl因为是多组输入
        cout << (diff + 1) << endl ;
    }


}
c 复制代码
int main()
{
    int a, b;
    while (cin >> a >> b)
    {
        int y1 = a / 10000, m1 = a / 100 % 100, d1 = a % 100;
        //这里用的是b不是a
        int y2 = b / 10000, m2 = b / 100 % 100, d2 = b % 100;
        //想取数字中的3、4位先/ 100 再 % 100
        long long diff = calc(y1, m1, d1) - calc(y2, m2, d2);
        //取值和函数返回值都取long long是因为转化数据太大
        //最后要求打印的值为整数
        if (diff < 0) diff = -diff;
        //日期差值为 diff + 1
        //最后是<<endl因为是多组输入
        cout << (diff + 1) << endl ;
    }

//如果这里我们用char数组或字符串得到年月日都这个方法方便

这里传入两个整型变量后要将 它们对应的年月日求出来

(y1, m1,d1,y2,m2,d2)

我们要知道得到某整数的3、4位要先 / 100 再 % 100记得到3、4位的值(引用这个我们可以求得某整数想要的位数上的值)

long long diff = calc(y1, m1, d1) - calc(y2, m2, d2);

变量和返回类型都用long long 类型防止超出最大范围

c 复制代码
long long calc(int y, int m, int d)
{
    long long days = 0;
    // 先算年一共有多少天
    //这里i = y - 1,第y年全年不算该年月日后面会补
    for (int i = y - 1; i > 0; i--) days += isleap(i) ? 366 : 365;
    //再算月一共有多少天
    for (int i = 1; i < m; i++)
    {
        days += dm[i];
        //这里是i == 2不是m == 2
        if (i == 2 && isleap(y)) days++;
    }
    //最后返回 天数加剩余的天数
    return days + d;
}

这里没啥讲的注意循环计天数的时候不要把下标与y、m用混了它们的变化顺序不同

if (diff < 0) diff = -diff;

最后得到的差值是负数就变成正的

最后打印差值加1(打印差值加1就是两日期差)


3.求1+2+3+...+n

这里如果用递归最后要条件语句才可结束

这里我们实现等差数列和利用静态成员函数和变量以及构造函数实现

这些类和对象的东西我就不讲了之前的文章里有

这里是核心代码模式不用全写

c 复制代码
class Sum {
  public:
    Sum() {
        _ret += _i;
        ++_i;
    }
    static int GetRet()
    {
        return _ret;
    }

//   private:
    static int _i ;
    static int _ret;
};
int Sum::  _i  = 1;
int Sum:: _ret = 0;
class Solution {

  public:
    int Sum_Solution(int n) {
        Sum* arr = new Sum[n];
        int ret  = Sum::GetRet();
        return ret;
    }
};

这里我们弄一个类数组用new申请空间(new会将类数组里的类元素都调用构造函数)

因为静态成员变量在类里面调用n个构造函数,静态成员变量_ret实现了等差数列求和

return Sum::GetRet();

这么写更好

这静态成员函数不用对象返回静态成员变量,免去繁琐步骤


4.打印日期

注意这里是多组输入要用while

然后就是怎么打印0x的月和日

描述

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

就是构造函数不要给月日传0、0要传1、1一年的第一天也是一月一日

这种题不要想着用字符串会更复杂

c 复制代码
#include<iostream>
#include<cassert>
using namespace std;
class Date {
  public:
    Date(int year, int month, int day) {
        //要初始化成员变量才叫构造函数
        //不写报错
        _year = year;
        _month = month;
        _day = day;
    }
    int GetMonthDay(int year, int month) {
        assert(month > 0 && month < 13);
        int a[13] = {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        //这里是month == 2,不是month = 2(这是赋值)
        if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) {
            return 29;
        } else {
            return a[month];
        }
    }
    //外部自定义函数无法访问类私有成员
    void GetDate(int Sum) {
        while (Sum > GetMonthDay(_year, _month))
        {
              Sum -= GetMonthDay(_year, _month);
              _month++;
        }
        _day = Sum ;
    }
    void Print()
    {
        PrintYear();
        PrintMonth();
        Printday();
        cout << endl;
    }
   void PrintYear()
   {
    cout << _year << "-";
   }
   void PrintMonth()
   {
    //   if(_month >= 0 && _month <= 9)
    //   这里_month >= 1因为月没有0
      if(_month >= 1 && _month <= 9)
      {
        cout << 0 << _month << "-";
        return;
      }
       cout << _month << "-";
   }
   void Printday()
   {
    if(_day >= 0 && _day <=9)
    {
        cout << 0 << _day;
        return;
    }
    cout << _day;
   }
  private:
    int _year;
    int _month;
    int _day;
};




int main() {
    int a, b;
    while (cin >> a >> b) {
        //月和日都传入1,月和日没有0
        Date d(a, 1, 1);
         d.GetDate(b);
        d.Print();
    }

    return 0;
}

主要讲转换天数和打印

c 复制代码
void GetDate(int Sum) {
        while (Sum > GetMonthDay(_year, _month))
        {
              Sum -= GetMonthDay(_year, _month);
              _month++;
        }
        _day = Sum ;
    }

这里年不会变从一月开始只要Sum大于该月天数就减该月天数

将_month++最后将剩余的天数加到_day即可

c 复制代码
 void Print()
    {
        PrintYear();
        PrintMonth();
        Printday();
        cout << endl;
    }
   void PrintYear()
   {
    cout << _year << "-";
   }
   void PrintMonth()
   {
    //   if(_month >= 0 && _month <= 9)
    //   这里_month >= 1因为月没有0
      if(_month >= 1 && _month <= 9)
      {
        cout << 0 << _month << "-";
        return;
      }
       cout << _month << "-";
   }
   void Printday()
   {
    if(_day >= 0 && _day <=9)
    {
        cout << 0 << _day;
        return;
    }
    cout << _day;
   }

这里打印就要考虑当月份和日在0到9之间的打印方式

其余一般都写得出来

5.类似拓展题

这题和4差不多链接如下有兴趣可以做一下:

日期累加


文章到这就告一段落,希望对你有所帮助,感谢观看!

相关推荐
All for pursuit.1 小时前
【二叉树-10】114.二叉树展开为链表
数据结构·c++·算法·leetcode·链表
叠层归一研究院1 小时前
区分预算与通道诱导:Ω–L叠层体系的观测赋值与定量验证
人工智能·算法
多弗朗皮卡丘1 小时前
C++string类
c++
BYSJMG2 小时前
计算机毕业设计选题推荐:基于大数据的快递物流运营数据分析与可视化,Spark与K-Means
大数据·算法·数据分析·spark·课程设计
阳明山水2 小时前
因果一致性正则化实战解析
人工智能·深度学习·算法·机器学习·架构
Yunovian3 小时前
AI时代,针对模型与应用,浅谈一下各编程语言
开发语言·c++·人工智能·python·ai·rust·ai编程
黄金龙PLUS3 小时前
5个1024比特大状态置换算法的设计与分析
算法·网络安全·密码学·哈希算法·同态加密
周杰伦fans4 小时前
构建真正智能的CAD AI绘图代理
开发语言·人工智能·c#
心中有你02144 小时前
C语言埃氏筛法(素数筛选)
c语言·数据结构·算法