【41-45】剑指offer

41.题目描述

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck! 

输出描述:

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

思路:采用两个指针分别指向小数据的一端和大数据的一端,如果满足当前两个指针之间的数据之和等于sum,则找到一组满足要求的数据。如果当前的和大于sum则持续改进nSmall指导不满足条件,改进的过程中如果满足当前两个指针之间的数据之和等于sum,则找到一组满足要求的数据。否则nBig自加,nCurSum加上nBig。

注意:二维容器的使用,例如:vector<vector<int> > number,它是将vector<int>变量作为元素的一元容器。

 

#include <iostream>

#include <vector>

using namespace std;

 

class Solution {

public:

   vector<vector<int> > FindContinuousSequence(int sum) {

              //如果sum小于3,这说明不存在这样的情况,输入不合法

              if(sum< 3)

                     returnvector<vector<int> >(0, vector<int>(0));

 

              vector<vector<int>> naResult;

              vector<vector<int>>::iterator iteResult = naResult.begin();

              intnSmall = 1;

              intnBig = 2; 

              intnMid = (sum+1)/2;//当sum为2个数的和时,其最大的值为sum/2+1,最小值为sum/2;

              intnCurSum = nSmall + nBig;

 

              while(nSmall< nMid)

              {

                     //当当前的nCurSum与sum相等时,则打印nSmall与nBig之间的数据

                     if(nCurSum== sum)

                     {

                            inti = nSmall;

                            /*vector<int>result(nBig - nSmall + 1);

                            vector<int>::iteratorite = result.begin();

                            for(; ite != result.end(); ite++)

                            {

                                   *ite= i++;

                            }*/

                            //以上注释的部分也能实现数据的保存

                            vector<int>result;

                            for(;i <= nBig; i++)

                                   result.push_back(i);

                            naResult.push_back(result);

                           

                     }

                     //当当前的nCurSum大于sum时

                     while(nCurSum> sum && nSmall < nMid)

                     {

                            nCurSum-= nSmall;

                            nSmall++;

 

                            if(nCurSum== sum)

                            {

                                   inti = nSmall;

                                   /*vector<int>result(nBig - nSmall + 1);

                                   vector<int>::iteratorite = result.begin();

                                   for(; ite != result.end(); ite++)

                                   {

                                          *ite= i++;

                                   }*/

                                   //以上注释的部分也能实现数据的保存

                                   vector<int>result;

                                   for(;i <= nBig; i++)

                                          result.push_back(i);

                                   naResult.push_back(result);

                            }

                     }                         

                     nBig++;

                     nCurSum+= nBig;

              }

              returnnaResult;

    }

};

 

int main()

{

       Solutions;

       vector<vector<int>> result = s.FindContinuousSequence(9);

       vector<vector<int>>::iterator ite1 = result.begin();

       vector<int>::iteratorite2 = ite1->begin();

       for(ite1= result.begin(); ite1 != result.end(); ite1++)

       {

              for(ite2= ite1->begin(); ite2 != ite1->end(); ite2++)

              {

                     cout<<*ite2<<"";

              }

              cout<<endl;

       }

      

       return0;

}

 

42.题目描述

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

输出描述:

对应每个测试案例,输出两个数,小的先输出。

思路:本题目与41题相似,只需要用两个指针,一个指针指向数组的最前面,另一个指针指向数组的最后面。将两指针分别向中间移动,当找到满足条件的第一个即为乘机最小,即可直接得到正确的答案。具体实现见代码:

 

#include <iostream>

#include <vector>

using namespace std;

 

class Solution {

public:

   vector<int> FindNumbersWithSum(vector<int> array,int sum) {

       //如果数组元素个数少于2个则返回空

              if(array.size()< 2)

                     returnvector<int>(0);

             

              vector<int>::iteratoriteSmall =  array.begin();

              vector<int>::iteratoriteBig = array.end()-1;

              intnCurSum = *iteBig + *iteSmall;

 

              while(iteSmall< iteBig)

              {

                     if(nCurSum== sum)

                     {

                            vector<int>result;

                            result.push_back(*iteSmall);

                            result.push_back(*iteBig);

                            returnresult;

                     }

 

                     while(iteSmall< iteBig && nCurSum > sum)

                     {

                            iteBig--;

                            nCurSum= *iteSmall + *iteBig;

 

                            if(nCurSum== sum)

                            {

                                   vector<int>result;

                                   result.push_back(*iteSmall);

                                   result.push_back(*iteBig);

                                   returnresult;

                            }    

                     }

                     iteSmall++;

                     nCurSum= *iteSmall + *iteBig;

              }

              returnvector<int>(0);

    }

};

 

int main()

{

       freopen("data.txt","r", stdin);

       vector<int>array(12);

       vector<int>::iteratorite = array.begin();

       for(;ite != array.end(); ite++)

              cin>>*ite;

 

       Solutions;

       vector<int>result = s.FindNumbersWithSum(array, 12);

       ite= result.begin();

       for(;ite != result.end(); ite++)

              cout<<*ite<<"";

       cout<<endl;

       return0;

}

 

43.题目描述

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

思路:1.先整体旋转字符转

      2.旋转前一部分字符串

      3.旋转后一部分字符串

 

#include <iostream>

#include <string>

using namespace std;

 

class Solution {

public:

   string LeftRotateString(string str, int n) {

              //如果str为NULL则返回空串,若n>字符串的长度,也返回空串

              intlen = str.size();

              cout<<len<<endl;

              if(len<= 0 || len < n)

                     return"";

             

              //整体旋转

              intnHead = 0;

              intnTail = len-1;

              while(nHead< nTail)

              {

                     charch = str[nHead];

                     str[nHead]= str[nTail];

                     str[nTail]= ch;

                     nHead++;

                     nTail--;

              }

              //前部分旋转

              nHead= 0;

              nTail= len-n-1;

              while(nHead< nTail)

              {

                     charch = str[nHead];

                     str[nHead]= str[nTail];

                     str[nTail]= ch;

                     nHead++;

                     nTail--;

              }

              //后部分旋转

              nHead= len-n;

              nTail= len-1;

              while(nHead< nTail)

              {

                     charch = str[nHead];

                     str[nHead]= str[nTail];

                     str[nTail]= ch;

                     nHead++;

                     nTail--;

              }

              returnstr;

    }

};

 

int main()

{

       stringstr1 = "abcXYZdef";

       cout<<str1<<endl;

 

       Solutions;

       stringstr = s.LeftRotateString(str1, 3);

       cout<<str<<endl;

 

       return0;

}

 

44.题目描述

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事CatFish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

思路:1.将字符串整体翻转

      2.以空格或者’\0’为分割,将被分割 字符串进行翻转

class Solution {

public:

   string ReverseSentence(string str) {

       //如果字符串为空,则返回空字符串

              if(str.size()<= 0)

                     return"";

              if(str.size()== 1)

                     returnstr;

 

              //整体翻转字符串

              intend = str.size()-1;

              intstart = 0;

              while(start< end)

              {

                     charch = str[start];

                     str[start]= str[end];

                     str[end]= ch;

                     start++;

                     end--;

              }

             

              //将以空格为分割的字符串进行翻转

              intnAhead = 0;

              intnTail = 0;

              while(str[nAhead]!= '\0')

              {

                     if(str[nAhead]== ' ')

                     {

                            nAhead++;

                            nTail++;

                     }

                     elseif(str[nTail] == ' ' || str[nTail] == '\0')

                     {

                            intnahead = nAhead;

                            intntail = --nTail;

                            while(nahead< ntail)

                            {

                                   charch = str[nahead];

                                   str[nahead]= str[ntail];

                                   str[ntail]= ch;

                                   nahead++;

                                   ntail--;

                            }

                            nAhead= ++nTail;

                     }

                     else

                            nTail++;

              }

              returnstr;

    }

};

 

45.题目描述

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\王可以看成任何数字,并且A看作1,J11,Q12,K13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作24),“So Lucky!”LL决定去买体育彩票啦。现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0

 

#include <iostream>

#include <vector>

using namespace std;

 

class Solution {

public:

   bool IsContinuous( vector<int> numbers ) {

              //如果数组的元素个数不是5,则返回false

              if(numbers.size()!= 5)

                     returnfalse;

              //对数进行排序

              for(inti = 0; i < numbers.size(); i++)

              {

                     for(intj = i; j < numbers.size(); j++)

                     {

                            if(numbers[i]> numbers[j])

                            {

                                   inttemp = numbers[i];

                                   numbers[i]= numbers[j];

                                   numbers[j]= temp;

                            }

                     }

              }

              //统计0的个数

              intnNumOfZero = 0;

              vector<int>::iteratorite = numbers.begin();

              for(;ite != numbers.end() && *ite == 0; ite++)

                     nNumOfZero++;

              cout<<nNumOfZero<<endl;

              //统计数之间的间隔数

              intnNumGap = 0;

              vector<int>::iteratoriteFirst = numbers.begin();

              vector<int>::iteratoriteSecond = iteFirst+1;

 

              while(iteSecond!= numbers.end())

              {    

                     if(nNumOfZero== 4)

                            returntrue;

                    

                     while(*iteFirst== 0 && iteSecond != numbers.end())

                     {

                            iteFirst= iteSecond++;

                     }

                    

                     if(*iteFirst== *iteSecond && *iteFirst != 0 && *iteSecond != 0)

                            returnfalse;

 

                     nNumGap+= (*iteSecond) - (*iteFirst) - 1;

                     iteFirst= iteSecond++;

              }

              cout<<nNumGap<<endl;

 

              if(nNumGap> nNumOfZero)

                     returnfalse;

              else

                     returntrue;

    }

};

 

int main()

{

       vector<int>array(5);

       vector<int>::iteratorite = array.begin();

       for(;ite != array.end(); ite++)

       {

              cout<<"Pleaseinput num:";

              cin>>*ite;

       }

      

       Solutions;

       if(s.IsContinuous(array))

              cout<<"Goodlucky!"<<endl;

       else

              cout<<"Badlucky!"<<endl;

      

       return0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值