【反思与总结---3】在线OJ③

二叉树最近公共祖先、求连续最大比特数

题目要求:

<1>.给定int a和int b作为结点编号
<2>.返回a和b的最近公共祖先

解题思路:

暂无,没做出来

代码示例:
暂无

题目要求:

<1>.输入一个数,将其转为二进制数
<2>.输出1连续出现的最大次数

解题思路:

<1>.按照之前做过的进制转换,写出进制转换的代码
<2>.按照之前做过的找出最大连续数字串的方法,统计1最大的连续的出现次数

之前写过的代码多看看,写过的再想用还是不太熟…

代码示例:

#include<iostream>
#include<algorithm>
#include<string>

using namespace std;

string Func(int a,int b)
{
    string s;
    string table{0123456789ABCDEF};

    bool symbol=false;

    if(a<0)
    {
        symbol=true;
        a=0-a;
    }

    while(a!=0)
    {
        s+=table[a%b];
        a/=b;
    }

    if(symbol==true)
    {
        s+='-';
    }

    reverse(s.begin(),s.end());

    return s;
}

int main()
{
    int A;

    while(cin>>A)
    {
        string s=Func(A,2);

        int count=0;
        int max=0;

        for(int i=0;i<s.length();++i)
        {
            while(s[i]==1)
            {
                count++;
                i++;

                if(i==s.size())
                {
                    break;
                }
            }

            if(count>=max)
            {
                max=count;
                count=0;
            }
        }

        cout<<max<<endl;
    }
    system("pause");
    return 0;
}

反思:

<1>.题目中描述的子节点与父节点的关系为root=child/2;
<2>.所以当a!=b时,循环比较a,b,让大的数/=2
<3>.当a,b相等时,得到的就是最近公共祖先的编号

正确代码示例:

class LCA 
{
public:
    int getLCA(int a, int b) 
    {
        while(a!=b)
        {
            if(a>b)
            {
                a/=2;
            }
            else
            {
                b/=2;
            }
        }
        return a;
    }
};

优先使用更简洁的方法,但是位运算好难理解…

正确代码示例:

#include<iostream>
#include<string>
#include<algorithm>

using namespace std;

int main()
{
    int n;
    
    while(cin>>n)
    {
        int count=0;
        int maxcount=0;
        
        while(n)
        {
            //获取当前位的二进制值
            if(n&1)
            {
                ++count;
                maxcount=max(count,maxcount);
            }
            else
            {
                count=0;
            }
            
            n=n>>1;
        }
        
        cout<<maxcount<<endl;
    }
    
    return 0;
}

二进制插入、组成偶数的两个最近的素数

题目要求:

<1>.给定两个32位整数m和n,将n的二进制数位插到m中的i~j位
<2>.示例:1024 19 2 6
<3>.输出插入后到数1100

解题思路:

<1>.1024 10000000000
<2>.11 10011
<3>.插到第2~6位 10001001100
<4>.输出这个新的数

代码示例:

class solution
{
    public:
        int binInsert(int n,int m,int j,int i)
        {
            m=m<<j;
            return n|m;
        }
};

题目要求:

<1>.任意一个偶数都可以由两个素数组成,输入一个偶数
<2>.输出两个素数(差值最小)
<3>.示例:20 —>7 13

解题思路:

<1>.先写一个判断是不是素数的函数
<2>.从中查找才能差值最小
<3>.找到一个之后另一个是输入的数减去找到的这个数
<4>.但是要确保另一个也是素数

代码示例:

#include<iostream>
#include<math.h>

using namespace std;

bool isprime(int a)
{
    int b=sqrt(a);

    for(int c=2;c<=b;++c)
    {
        if(a%c==0)
        {
            return false;
        }
    }
    return true;
}

int main()
{
    int m;

    while(c>>m)
    {
        for(int i=m/2;i>=2;--i)
        {
            if(isprime(i)==true&&isprime(m-i)==true)
            {
                cout<<i<<endl;
                cout<<m-i<<endl;
                break;
            }
        }
    }

    return 0;
}

参数解析、跳石板

题目要求:

<1>.输入一行字符串,可以有空格
<2>.输出参数个数,分解后的参数(每个参数占一行)

解题思路:

<1>.以空格和双引号为间隔,找出参数保存到string里
<2>.把所有的参数保存到vector中,输出vector的size,遍历vector打印

代码示例:

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main()
{
    string s;
    
    while(getline(cin,s))
    {
        bool flag=false;
        
        vector<string> v;
        
        string s1;
        
        for(int i=0;i<s.size();++i)
        {
            if(flag)
            {
                if(s[i]!='"')
                {
                    s1+=s[i];
                }
                else
                {
                    flag=false;
                }
            }
            else
            {
                if(s[i]==' ')
                {
                    v.push_back(s1);
                    s1="";
                }
                else if(s[i]=='"')
                {
                    flag=true;
                }
                else
                {
                    s1+=s[i];
                }
            }
        }
        v.push_back(s1);
        cout<<v.size()<<endl;
       
        for(auto e:v)
        {
            cout<<e<<endl;
        }
     }
    
     return 0;
}

题目要求:

<1>.从当前数字石板跳到目标石板
<2>.每次跳的步数为目标石板的一个约数
<3>.不能到达返回-1,可以到达返回需要的最少步数

据说是网易2017年真题,大厂就这么难吗?
我能说我看答案都没看懂吗??
这可怎么办?

正确代码示例:

**代码示例:**
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

void DivNum(int n,vector<int>& divNum)
{
    for(int i=2;i<=sqrt(n);++i)
    {
        if(n%i==0)
        {
            divNum.push_back(i);

            if(n/i!=i)
            {
                divNum.push_back(i);
            }
        }
    }
}

int Jump(int N,int M)
{
    //储存到达此stepNum点的步数,初始N为一步,从N到M为一步
    vector<int> stepNum(M+1,0);

    stepNum[N]=1;//最后返回的时候需要减一

    for(int i=N;i<M;++i)
    {
        vector<int> divNum;

        if(stepNum[i]==0)
        {
            continue;
        }

        //求出所有可以走的步数 ,存到divNum中
        DivNum(i,divNum);

        for(int j=0;j<divNum.size();++j)
        {
            if((divNum[j]+1)<=M&&stepNum[divNum[j]+1]!=0)
            {
                stepNum[divNum[j]+1]=min(stepNum[divNum[j]+1],stepNum[i]+1);
            }
            else if((divNum[j]+1)<=M)
            {
                stepNum[divNum[j]+1]=stepNum[i]+1;
            }
        }

        if(stepNum[M]==0)
        {
            return -1;
        }
        else
        {
            return stepNum[M]-1;
        }
    }
}

int main()
{
    int n,m;

    while(cin>>n>>m)
    {
        cout<<Jump(n,m)<<endl;
    }

    system("pause");
    return 0;
}

计算天数、幸运的袋子

题目要求:

<1>.输入三行,分别为年月日
<2>.输出当前日期在这一年中的天数

解题思路:

<1>.这都已经不知道写过多少遍了,完善日期类的时候就写过了
<2>.判断是否是闰年,闰年2月29天
<3>.遍历月份,获取每月天数,累加到sum
<4>.把最后一个月的当前天数累加到sum
<5>.输出sum

代码示例:

#include<iostream>
#include<vector>

using namespace std;

bool isYear(int year)
{
	if ((year % 100 != 0 && year % 4 == 0) || year % 400 == 0)
	{
		return true;
	}
	return false;
}

int GetMonthDay(int year, int month)
{
	vector<int> days{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

	if (isYear(year) == true)
	{
		days[2] = 29;
	}
	return days[month];
}

int Description(int year, int month, int day)
{
	int sum = 0;

	for (int i = 1; i < month; ++i)
	{
		sum += GetMonthDay(year, i);
	}
	sum += day;

	return sum;
}

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

	while (cin >> year >> month >> day)
	{
		cout << Description(year, month, day) << endl;
	}

	system("pause");
	return 0;
}

题目要求:

<1>.幸运的袋子就是所有数的和大于所有数的乘积
<2>.现在可以适当从袋子里移除一些球(可以移除0个,但是别移除完)
<3>.求出移植之后袋子还是幸运的的个数

我把题意理解错了,我以为一次只能移除一个,但是不是这样的
所以这个题我不会,那20%通过是题目送的…

反思:

深度优先遍历,暂时还没了解到…慢慢弄懂…

正确代码示例:

#include<iostream>
#include<algorithm>

using namespace std;

int GetLuckyPacket(int x[],int n,int pos,int sum,int multi)
{
    int count=0;
    
    for(int i=pos;i<n;++i)
    {
        sum+=x[i];
        multi*=x[i];
        
        if(sum>multi)
        {
            count+=1+GetLuckyPacket(x,n,i+1,sum,multi);
        }
        else if(x[i]==1)
        {
            count+=GetLuckyPacket(x,n,i+1,sum,multi);
        }
        else
        {
            break;
        }
        
        sum-=x[i];
        multi/=x[i];
        
        while(i<n-1&&x[i]==x[i+1])
        {
            i++;
        }
    }
    return count;
}

int main()
{
    int n;
    
    while(cin>>n)
    {
        int x[n];
        
        for(int i=0;i<n;++i)
        {
            cin>>x[i];
        }
        
        sort(x,x+n);
        
        cout<<GetLuckyPacket(x,n,0,0,1)<<endl;
    }
    return 0;
}

二进制1的个数、手套

题目要求:

输入一个数,求出二进制中1出现的次数

解题思路:

<1>.最近的题都是第一道很简单,第二道很难…起码我觉得是…
<2>.前面做过类似的题,while(n),里面每次n>>=1,就遍历了n的每一位
<3>.n&1,就取出了每一位的值,判断是否和1相等,相等count++
<4>.输出count的值

代码示例:

#include<iostream>

using namespace std;

int findNumberOf1(int num)
{
    int count=0;

    while(num)
    {
        if((num&1)==1)
        {
            count++;
        }
        num>>=1;
    }
    return count;
}

int main()
{
    int n;

    while(cin>>n)
    {
        cout<<findNumberOf1(n)<<endl;
    }

    system("pause");
    return 0;
}

算法基础太差…无从入手的感觉…

题目要求:

<1>.题目要求呢…没记下…因为题我根本就没读懂

解题思路:

<1>.没有思路…

代码示例:

暂无

反思:

对于非零递增序列,a1,a2…an,要想最终取值覆盖每个种类n=sum(a1…an)-a1+1,(也就是总数减去最小值之后+1),所以对于左右手手套颜色都有数量的序列,想要覆盖每一种颜色,则最小数量leftsum=左边数量和-左边最小值+1,rightsum=右边数量和-右边最小值+1,而对于有0存在的,则需要做累加,保证覆盖每一种颜色

正确代码示例:

class Gloves 
{
public:
	int findMinimum(int n, vector<int> left, vector<int> right) 
	{
		int left_sum = 0, left_min = INT_MAX;
		int right_sum = 0, right_min = INT_MAX;
		int sum = 0;

		//遍历每一种颜色的左右手套序列
		for (int i = 0; i < n; i++)
		{
			//对于有0存在的颜色手套,累加
			if (left[i] * right[i] == 0)
			{
				sum += left[i] + right[i];
			}

			//对于左右手都有的颜色手套,执行累加-最小值+1
			//找到最小值和总数
			else
			{
				left_sum += left[i];
				right_sum += right[i];
				left_min = min(left_min, left[i]);
				right_min = min(right_min, right[i]);
			}
		}

		//结果为有左右都有数量的手套序列的结果+有0存在的手套数+最后再加一肯定就能保证了
		return sum + min(left_sum - left_min + 1, right_sum - right_min + 1) + 1;
	}
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值