【31-35】剑指offer

来源:互联网 发布:jsp调用java显示图片 编辑:程序博客网 时间:2024/05/23 14:21

31.题目描述

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有110111213因此共出现6,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。

思路:假设输入的数据为21345

first:代表第一位数据

numFirstDigit:代表高位1的个数

numOtherDigit:代表其他为1的个数

numRecusive:代表递归求取1的个数

如果first>1: numFirstDigit=10^(length-1)

如果first==1: numFirstDigit=atoi(strN+1)+1;

numOtherDigit = first*(length-1)*10^(length-2);

递归求取:numRecusive = NumberOf1(strN+1);

具体详见程序:

 

#include <iostream>

using namespace std;

 

class Solution {

public:

   int NumberOf1Between1AndN_Solution(int n)

    {

              //如果输入大数据小于等于0,则返回0

              if(n<= 0)

                     return0;

              //将数据转化成字符串

              charstrN[50];

              sprintf(strN,"%d", n);

              //返回1出现的次数

              returnNumberOf1(strN);

    }

 

       intNumberOf1(const char * strN)

       {

              //检查输入的数据的合法性

              if(!strN|| *strN < '0' || *strN > '9' || *strN == '\0')

                     return0;

             

              intfirst = *strN - '0';

              unsignedint length = static_cast<unsigned int>(strlen(strN));

 

              //如果输入的数据是1位数,则有以下两种情况

              if(length== 1 && first == 0)

                     return0;

              if(length== 1 && first > 0)

                     return1;

 

              //如果数据的数据是多为位数,则分三种情况

              intnumFirstDigit = 0;

              if(first> 1)

                     numFirstDigit= PowerBase10(length - 1);

              elseif(first == 1)

                     numFirstDigit= atoi(strN+1)+1;

 

              intnumOtherDigit = first*(length - 1)*PowerBase10(length - 2);

 

              intnumRecusive = NumberOf1(strN+1);

 

              returnnumFirstDigit + numOtherDigit + numRecusive;

       }

 

       intPowerBase10(unsigned int n)

       {

              intresult = 1;

              for(unsignedint i = 0; i < n; i++)

              {

                     result*= 10;

              }

              returnresult;

       }

};

 

int main()

{

       Solutions;

       cout<<s.NumberOf1Between1AndN_Solution(10)<<endl;

       cout<<s.NumberOf1Between1AndN_Solution(101)<<endl;

       cout<<s.NumberOf1Between1AndN_Solution(1032)<<endl;

       cout<<s.NumberOf1Between1AndN_Solution(21345)<<endl;

       return0;

}

 

32.题目描述

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{332321},则打印出这三个数字能排成的最小数字为321323

   思路:采用库函数qsort算法,并添加比较函数compare。具体实现见代码:

#include <iostream>

#include <vector>

#include <string>

using namespace std;

 

const int g_MaxNumberLength = 10;

 

int compare(const void *strNumber1, constvoid *strNumber2)

{    

   char g_StrCombine1[g_MaxNumberLength*2 + 1]={'\0'};

       charg_StrCombine2[g_MaxNumberLength*2 + 1]={'\0'};

   

       strcpy(g_StrCombine1,*(constchar **)strNumber1);

       strcat(g_StrCombine1,*(constchar **)strNumber2);

 

       strcpy(g_StrCombine2,*(constchar **)strNumber2);

       strcat(g_StrCombine2,*(constchar **)strNumber1);

      

       returnstrcmp(g_StrCombine1, g_StrCombine2);

}

      

class Solution {

public:

   string PrintMinNumber(vector<int> numbers) {

       string str = "";

       int length = numbers.size();

              inti = 0;

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

              if(length== 0)

                     returnstr;

       //如果数组有小于0的数,则返回空字符串

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

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

                     if(*ite< 0)

                            returnstr;

              //如果字符串不为空,且数组满足要求

              //char**strNumbers = (char **)(new int[length]); //书上该句存在问题?下面两种内存分配都可以

              //char**strNumbers = new char*[4*length];

              char**strNumbers = (char **)(new int*[length]);

              intcount = 0;

              for(i= 0; i < length; i++)

              {

                     if(numbers[i]== 0)

                            continue;

                     strNumbers[count]= new char[g_MaxNumberLength + 1];

                     sprintf(strNumbers[count],"%d",numbers[i]);

                     count++;

              }

              //调用库函数进行排序

              qsort(strNumbers,count, sizeof(char*), compare);

             

              //输出排序后的数据

              for(i= 0; i < count; i++)

              {

                     str+= strNumbers[i];

              }

 

              //清理分配的内存

              for(i= 0; i < count; i++)

                     delete[]strNumbers[i];

              delete[]strNumbers;

 

              returnstr;

    }

};

 

int main()

{

       vector<int>array(5);

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

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

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

              cin>>*ite;

 

       Solutions;

       cout<<s.PrintMinNumber(array)<<endl;

 

       return0;

}

 

33.题目描述

把只包含因子235的数称作丑数(Ugly Number)。例如68都是丑数,但14不是,因为它包含因子7习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

 

#include <iostream>

using namespace std;

 

class Solution {

public:

       intMin(int a, int b, int c)

       {

              intmin = (a > b) ? b:a;

              return(min > c)? c:min;

       }

      

   int GetUglyNumber_Solution(int index) {

              if(index<= 0)

                     return0;

              //存放丑数

              int*pUglyNumber = new int[index];

              if(pUglyNumber== NULL)

                     return0;

              pUglyNumber[0]= 1;

              intnextUglyNumber = 1;

              int*p2 = pUglyNumber;

              int*p3 = pUglyNumber;

              int*p5 = pUglyNumber;

 

              while(nextUglyNumber< index)

              {

                     intmin = Min(*p2*2, *p3*3, *p5*5);

                     pUglyNumber[nextUglyNumber]= min;

                     cout<<min<<endl;

 

                     while((*p2)*2<= pUglyNumber[nextUglyNumber])

                            p2++;

                     while((*p3)*3<= pUglyNumber[nextUglyNumber])

                            p3++;

                     while((*p5)*5<= pUglyNumber[nextUglyNumber])

                            p5++;

 

                     nextUglyNumber++;

              }

              intUglyNum = pUglyNumber[nextUglyNumber-1];

              delete[] pUglyNumber;

              returnUglyNum;

    }

};

 

int main()

{

       Solutions;

       cout<<s.GetUglyNumber_Solution(1500)<<endl;

      

       return0;

}

 

34.题目描述

在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置

    思路:创建哈希表,实现查找时间复杂度为O(1).第一次遍历,获得每个字符出现的次数;第二次遍历获得只出现一且第一次出现的字符。通过变量position来记录字符的位置。具体实现见代码:

 

#include<iostream>

using namespace std;

 

class Solution {

public:

   int FirstNotRepeatingChar(string str) {

       int hasTable[256];

              for(inti = 0; i < 256; i++)

                     hasTable[i]= 0;

              char*pCh = &str[0];

              while(*pCh!= '\0')

              {

                     hasTable[*pCh]++;

                     pCh++;

              }

 

              pCh= &str[0];

              intposition = -1;

              while(*pCh!= '\0')

              {

                     position++;

                     if(hasTable[*pCh]== 1)

                            returnposition;

                     pCh++;

              }

              return-1;

    }

};

 

int main()

{

       Solutions;

       cout<<s.FirstNotRepeatingChar("abdgesdaga")<<endl;

 

       return0;

}

 

35.题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P1000000007取模的结果输出。即输出P%1000000007 

输入描述:

题目保证输入的数组中没有的相同的数字

数据范围:

       对于%50的数据,size<=10^4

       对于%75的数据,size<=10^5

       对于%100的数据,size<=2*10^5

 

输入例子:

1,2,3,4,5,6,7,0

 

输出例子:

7

   思路:采用基于归并排序的方式统计逆序对的数据,具体见代码(注意数据类型的选择):

#include <iostream>

#include <vector>

using namespace std;

 

class Solution {

public:

   int InversePairs(vector<int> data) {

              //如果数组的长度为0,则返回0

              if(data.size()== 0)

                     return0;

              //否则采用基于归并的方法统计逆序对的数目

              vector<int>copy(data.size());

              copy= data;

              longint count = InversePairsCores(data, copy, 0, data.size()-1);

              returncount%1000000007;

    }

 

       longint InversePairsCores(vector<int> &data, vector<int> &copy,int start, int end)

       {

              //当start==end时,返回0

              if(start== end)

              {

                     copy[start]= data[start];

                     return0;

              }

              //否则,递归左右两边的数组

              intlength = (end - start)/2;

              longint left = InversePairsCores(copy, data, start, start+length);

              longint right = InversePairsCores(copy, data, start+length+1, end);

 

              //进行归并计数

              longint count = MergeCount(copy, data, start, end, length);

              returncount + left + right;

       }

 

       longint MergeCount(vector<int> &data, vector<int> &copy, intstart, int end, int length)

       {

              inti = start + length;

              intj = end;

              longint count = 0;

              intindexCopy = end;

             

              while(i>= start && j >= start + length + 1)

              {

                     //满足逆序对的条件,count++,且将最大的数据拷贝到copy中。

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

                     {

                            copy[indexCopy--]= data[i--];

                            count+= j - start - length; //这一句不是很明白??

                     }

                     else//否则,直接拷贝,count不变

                     {

                            copy[indexCopy--]= data[j--];

                     }

              }

              //若未归并完,则继续归并

              for(;i >= start; i--)

                     copy[indexCopy--]= data[i];

              for(;j >= start+length+1; j--)

                     copy[indexCopy--]= data[j];

 

              returncount;

       }

};

 

int main()

{

       vector<int>data(4);

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

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

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

       {

              cin>>*ite;

       }

 

       Solutions;

       cout<<s.InversePairs(data)<<endl;

 

       return0;

}
0 0
原创粉丝点击