第六周作业

第一题

这个题目其实本质上和之前的计算月份的题目区别不是很大,这里主要有个技巧就是,我们只需要知道某一个月的13号是星期几,接下来就是依次增加一个月的天数再对7取余再加一即可得到下一个13号是星期几。
思路有了,具体的算法呢?不妨先从简单的算起,我们先计算1900年的每个月的13号

  • 首先是1月13号,这个很显然就是1月1号过去12天嘛,容易计算得出1月13号是星期6
  • 接下来是2月13号,因为1月13号到2月13号这中间跨过了一个1月的尾巴嘛,跨过了哪个月的月末,加上去的天数就是那一个月的天数,这样很容易就能发现2月13号对应的星期的序号就是(6+31)%7+1=2,同学们可以自己验证一下,至于为啥,一周7天一个循环嘛,很容易就可以想到取余操作
  • 随后的每一个月都是一样的操作,一直到12月
    现在我们已经有了1900年的13号对应星期几,那么基于1900年12月13号是星期几计算1901年1月13号该怎么做呢,一样的道理的,按照之前的规则往下迭代即可
#include<iostream>
using namespace std;
int main()
{
    int daysCount[7]={0};
    int months[12]={31,31,28,31,30,31,30,31,31,30,31,30};//先是12月,再是1月开始
    int year=0;
    bool needAdd=false;
    int currentYear=0;
    bool firstRound=true;
    int day13=0;
    cin >>year;
    for(int i=0;i<year;i++)
    {
        currentYear=1900+i;
        needAdd=false;
        if((currentYear%400==0)||(currentYear%4==0&&currentYear%100!=0))
        {
            needAdd=true;
        }
        for(int j=0;j<12;j++)
        {
            if(firstRound&&j==0)
            {
                day13=(day13+12)%7;
                firstRound=false;
            }
            else
            {
                if (j==2&&needAdd)
                {
                    day13++;
                }
                day13=(day13+months[j])%7;
            }
            daysCount[day13]+=1;
        }
    }
    for(int i=0;i<7;i++)
    {
        cout << daysCount[i]<<" ";
    }
    return 0;
}

第二题

这个题目首先需要了解的是如何处理输入,这一块可以参考题目中的提示这一部分,这是一个很经典的处理输入的方法,记住就好,接下来就是判断数组中的数字是否有重复,这一个地方由于允许使用另外的数组,所以其实还是比较简单的,另第二个数组存放最终的输出结果,对原数组进行遍历,每次检查原数组对应元素是否出现在第二个数组即可,当然有兴趣的同学可以研究一下哈希算法,这种算法可以很简单地实现去重的目的,C++中常见的对应数据结构为哈希表

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int nums[100]={0};
    int count=0;
    int x=0;
    while(cin >>x)
    {
        nums[count++]=x;
    }
    int ans[count]={0};
    int ansIndex=0;
    bool notFound=true;
    for(int i=0;i<count;i++)
    {
        notFound = true;
        for(int j=0;j<ansIndex;j++)
        {
            if(ans[j]==nums[i])
            {
                notFound=false;
                break;
            }
        }
        if(notFound)
        {
            ans[ansIndex++]=nums[i];
        }
    }
    for(int i=0;i<ansIndex;i++)
    {
        cout <<ans[i]<<" ";
    }
    return 0;
}

第三题

这个题目如果限制不允许使用第二个数组难度就大起来了,因为题目要求的是按照原来的顺序输出,这就限制了我们使用sort随后去重的手段,那么思路就得发生一些转变

  • 首先是要求数组元素按照首次出现顺序输出,所以自然想得到我们要将后面的重复数字删除,所以不妨从后往前遍历,对每个数字,如果数组在它之前有它的重复元素,那么就将它剔除(此处用到的方法是置0,因为题目给出了元素的范围),这样就可以轻松得到一个含有多余的0的数组
  • 接下来,题目要求输出的时候不能额外判断,那该怎么办呢,就需要将所有的0后置。这个就涉及到之前提及的双指针的思想,我们可以用一个指针cur遍历数组,同时用另一个指针pre指向当前的非零数组的下一位,每次cur遍历到0,则将cur往后移动到cur指向的元素非0或者遍历完成,将非零的数据移动到pre指向的位置,重复这个思路就可以将所有非0元素移动到0之前
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
   int a[100];
   int n=0;

   while (cin>>a[n])
   {
       n++;
   }

   for (int i=n-1;i>=0;i--)
   {
       for (int j=i-1;j>=0;j--)
       {
           if (a[j]==a[i]) {
               a[i]=0;
               break;
           }
       }
   }
   //所有的数字移动到0的前面
   int pre=0;
   int current=0;
   while(current<n)
   {
       if(a[current]==0)
       {
           while(current<n&&a[current]==0)
               current++;
           if(current<n)
           {
               a[pre++]=a[current++];
           }
       }
       else
       {
           a[pre++]=a[current++];
       }
   }
   for (int i=0;i<pre;i++)
   {
        cout<<a[i]<<" ";
   }
   return 0;
}

第四题

进制转换是非常经典的题目了,之前也应该提到过,转化为n进制,就是不断重复取余和相除这两个操作值得一提的是,当前字符应该是插入已生成字符的前面,否则最后结果需要逆序一下,转化的这个部分就不赘述了。主要讲下回文的判断,这个还是老办法,一个双指针就可以解决,设立头尾两个指针,每次判断完之后指针向中间移动知道相遇,这样就可以判断这个字符串是否关于中心对称,也就是是否是回文子字符串

#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
using namespace std;

int main()
{

    int B;
    cin>>B;

    for (int i=1;i<=200;i++)
    {
        int m=i*i;
        int m1=i;
        string str1;
        while (m1!=0)
        {
            if (m1%B < 10)
            {
                str1=to_string(m1%B)+str1;
            }
            else
            {
                str1=string(1,'A'+(m1%B)-10)+str1;
            }
            m1/=B;
        }
        
        string str;
        while (m!=0)
        {
            if (m%B < 10)
            {
                str=to_string(m%B)+str;
            }
            else
            {
                str=string(1,'A'+(m%B)-10)+str;
            }
            m/=B;
        }

        bool flag=true;
        for (int j=0;j<str.length()/2;j++)
        {
            if (str[j]!=str[str.length()-1-j])
            {
                flag=false;
                break;
            }
        }

        if (flag) cout<<str1<<" "<<str<<endl;


    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值