C++题目 代码

来源:互联网 发布:mac 拷贝文件夹 命令 编辑:程序博客网 时间:2024/05/09 07:55

1)实现string   toHex(int)把一个十进制转换成十六进制。(完全用算法实现)

string toHex(int a)
{
    int u_value=a>0?a:-a;
    char *value=new char[10];
    value[9]='\0';
    value[8]='H';
    int position=7;
    do
    {
        int yushu=u_value%16;
        value[position--]=yushu>9?yushu+'A'-10:yushu+'0'-0;
        u_value=u_value/16;
    }while(u_value!=0);

    if(a<0)
        value[position--]='-';
    string res(value,position+1,9-(position+1)+1);
    return res;


}

比较好的方法:

//作者:sutra(只回答经典问题 只提供经典答案)string ToHex( int i ){ string strHex, strCh ; string Table[] = {  "0", "1", "2", "3",  "4", "5", "5", "4",  "8", "9", "A", "B",  "C", "D", "E", "F" } ; while( i ) {  strHex = Table[ i&0xF ] + strHex ;  i >>= 4 ; } return strHex ;}

2)实现一个计算大位数(如100位以上)相乘结果的函数string   multiply(sting,string)。(请完全用算法实现)

我开始写了int 型的multiple的相加

代码如下

int add(int a,int b){int sum=0;while(a&b!=0)/<span style="color:#ff0000;">/a&b考虑进位的时候的和 a&b   不考虑的和为 a^b   a+b=a&b<<1+a^b 由于不用加号+ </span> {<span style="color:#ff0000;">int jin_wei=(a&b)<<1;//进位的a=a^b;</span>b=jin_wei;}   <span style="color:#ff0000;"> a=a^b;</span>return a;}int multiple(int a,int b){int i,sum=0;<span style="color:#ff0000;">for(i=0;i<32;i++)//int 为4个字节 32位</span>{if(i>=1)b=b>>1;if(b&1==1){sum=add(sum,(int)pow(2,(double)i)*a);}}return sum;}
但是不符合本题的要求,由于大数据无法用int进行存储,用string存储

string  add(string result,int digit,int position)<span style="color:#ff0000;"> //result现在的string,表示当前乘法的临时和  position表示第几位  digit为position的数字</span>{string str;cout<<"result =  "<<result<<"  length()= "<<result.length()<<"  position="<<position<<endl;<span style="color:#ff0000;">if(result.length()<position)//当前的postion>result.length()  比如result="11" position=3 digit=4  则结果 result="411"</span>{result='0'+result;result[0]=digit+'0';return result;}position=result.length()-position;<span style="color:#ff0000;">//position在result中的位置</span>int A=digit;int B=result[position]-'0';int carry=0;while(A+B>9)<span style="color:#ff0000;">//进位的时候</span>{if(position==0)<span style="color:#ff0000;">//res[0]有进位的时候 要 res 0--->res.length()-1右移动后  res[0]=1</span>{result[0]=(A+B)%10+'0';char *tmp=new char[123];tmp[result.length()+1]='\0';for(int i=result.length()-1;i>=0;i--){tmp[i+1]=result[i];}tmp[0]='0'+1;int i;for(i=0;tmp[i]!='\0';i++){cout<<tmp[i]<<" ";}str.assign(tmp);return str;   }<span style="color:#ff0000;">result[position]=(A+B)%10+'0';carry=(A+B)/10;A=carry;position=position-1;B=result[position]-'0';</span>}    result[position]=A+B+'0';str=result;return str;}string   multiply(string  str1,string str2){int len_1=str1.length();int len_2=str2.length();int i,j;int carry=0,digit;string res;for(j=len_2-1;j>=0;j--){carry=0;for(i=len_1-1;i>=0;i--){digit=(str1[i]-'0')*(str2[j]-'0')+carry;carry=digit/10;digit=digit%10;cout<<"digit= "<<digit<<"  p="<<len_2+len_1-i-j-1<<endl;<span style="color:#ff0000;">res=add(res,digit,len_2+len_1-i-j-1);</span>}if(carry>0)//当i==0 有进位 {cout<<"carry ="<<carry<<" p= "<<len_2+len_1-i-j-1<<endl;<span style="color:#ff0000;">res=add(res,carry,len_2+len_1-i-j-1);</span>}}return res;}
以上程序经过测试的

3)上地理课时,四个学生回答我国四大淡水湖的大小时说:
        甲:洞庭湖最大,洪泽湖最小,鄱阳湖第三。
          乙:洪泽湖最大,洞庭湖最小,鄱阳湖第二,太湖第三
        丙:鄱阳湖最小,洞庭湖第三。
        丁:鄱阳湖最大,太湖最小,洪泽湖第二,洞庭湖第三。
对于每个湖的大小,每人仅答对了一个。请判断四个湖的大小。
请写出分析思路和代码。

用排列组合的思想来做,4个湖的共有12种,对每种进行判断,是否满足甲乙丙丁每人答对一题的条件

代码如下:

<span style="color:#000000;">void order(int n,int k,int a[]){int i,j,m,num;if(k==n-1)//判断{for(j=0;j<4;j++)//j个人  只有一个对的{num=0;for(m=0;m<4;m++)//m 为湖if(b[j][m]==a[m])num++;if(num!=1) return ;}for(i=0;i<n;i++)//i个湖{cout<<a[i]<<" ";}}else{for(i=k;i<n;i++){int swap=a[k];a[k]=a[i];a[i]=swap;order(n,k+1,a);swap=a[k];a[k]=a[i];a[i]=swap;}}}</span>

题目:输入一个单向链表,输出该链表中倒数第k 个结点。链表的倒数第0 个结点为链表的尾指针。

代码:

void ret_k(NODE3 *head,int k){NODE3 *pre=head;NODE3 *p=head;for(;k>0;k--){/*if(p->next)p=p->next;else{cout<<"sorry have not"<<endl;return;}*/if(p)p=p->next;else{cout<<"sorry have not"<<endl;return;}}while(p){pre=pre->next;p=p->next;}cout<<"倒数 "<<pre->elem<<endl;}


题目:输入一个已经按升序排序过的数组和一个数字, 在数组中查找两个数,使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。

对于2个数和的时候,代码如下

void search(int arr[],int n,int value){int i=0,j=n-1;while(i<j){if(arr[i]+arr[j]==value){cout<<arr[i]<<"+"<<arr[j]<<"="<<value<<endl;i++;j--;}else if(arr[i]+arr[j]>value){j--;}else{i++;}}}<span style="font-family:Arial, Helvetica, sans-serif;">.题目假定是,只要找出俩个数,的和等于给定的数,</span>

其实是,当给定一排数,
4,5,7,10,12
然后给定一个数,22。
就有俩种可能了。因为22=10+12=10+5+7。
而恰恰与第4题,有关联了。望大家继续思考下。:)。

用回溯法,深度遍历,代码如下:

void search_k(int arr[],int i,int &h,int value){if(i>=5){if(value!=0) return;for(i=0;i<h;i++)cout<<sum[i]<<"  ";cout<<endl;return;}for(int  j=0;j<2;j++){if(j==0){sum[h]=arr[i];h++;search_k(arr,i+1,h,value-arr[i]);h--;}else{search_k(arr,i+1,h,value);}}}

int _tmain(int argc, _TCHAR* argv[]){int arr[]={4,5,7,10,12};int h=0;search_k(arr,0,h,22)


编程求解: 输入两个整数n 和m,从数列1,2,3.......n 中随意取几个数, 使其和等于m ,要求将其中所有的可能组合列出来.

和背包0-1类似

代码如下:

list<int> list2;void find(int sum,int n)//1--->n 找出和为m{if(n<0||sum<0) return;if(sum==0){for(list<int>::iterator it=list2.begin();it!=list2.end();it++){cout<<*it<<"  ";}cout<<endl;return;}list2.push_back(n);find(sum-n,n-1);list2.pop_back();find(sum,n-1);}find(6,10);
<img alt="" src="http://img.blog.csdn.net/20140418103742984?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3VycGFzc2dvb2QxMjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />


30.在从1 到n 的正数中1 出现的次数 题目:输入一个整数n,求从1 到n 这n 个整数的十进制表示中1 出现的次数。 例如输入12,从1 到12 这些整数中包含1 的数字有1,10,11 和12,1 一共出现了5 次。 分析:这是一道广为流传的google 面试题。

分析:

假设ABCDE位一个数字

如果C=1的时候

假设ABCDE=23 1 45     100--199     1,100-1,199   ------->     22,100-22,199     23,100-23,145(45+1)

此时C=1的数字为  AB*100+DE+1;

如果C>1

假设ABCDE=23 7 45   100-199   ---------22,100-22,199    23,100-23,199

此时C位为1的 数字个数为  (AB+1)*100

当C==0的时候

假设 ABCDE=23 0 45   100-199  -------------22,100--22,199

此时C位为1的 数字个数为  AB*100

代码如下:

int digit2(int n)//1--1  2--10  3--1000{int cur,low,upper;int res=0;int factor=1;while(n/factor!=0){cur=(n/factor)%(factor*10);//取当前为upper=n/(factor*10);low=n%factor;//cout<<"upper="<<upper<<"  cur="<<cur<<" low="<<low<<endl;switch(cur){case 0:res+=upper*factor;break;case 1:res+=upper*factor+low+1;break;default:res+=(upper+1)*factor;break;}factor*=10;}return res;}


 经典的话语,在《C专家编程》10.3节的小启发里讲的很透彻:(以下这段文字及对比一定要认真分析!)

数组和指针参数是如何被编译器修改的?

数组名被改写成一个指针参数”规则并不是递归定义的。数组的数组会被改写成“数组的指针”,而不是“指针的指针”:

实参                                                     所匹配的形参

数组的数组          char c[8][10];                  char (*)[10];          数组指针

指针数组             char *c[10];                     char **c;               指针的指针

数组指针(行指针)  char (*c)[10];                  char (*c)[10];        不改变

指针的指针           char **c;                         char **c;               不改变

 47.创新工场: 求一个数组的最长递减子序列比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5, 4,3,2}

Scan from left to right, maintain a decreasing sequence. For each number, binary search in the decreasing sequence to see whether it can be substituted.

#include<cassert>#include<stack>using namespace std ;int BiSearch(int *A,int nTarget,int nLen);void FindLongestSequence(int *A,int nLen){int *index=new int[nLen];int *LDS=new int[nLen];index[0]=A[0];LDS[0]=1;int i;int indexLen=1;for (int i=1;i<nLen;i++){int pos=BiSearch(index,A[i],indexLen);cout<<"search value "<<A[i]<<endl;cout<<"scop "<<endl;for(int k=0;k<indexLen;k++){cout<<index[k]<<"  ";}cout<<endl;cout<<"pos= "<<pos<<endl;index[pos]=A[i];LDS[i]=pos+1;if(pos>=indexLen)indexLen++;}cout<<"----LDS---"<<endl;for (i=nLen-1;i>=0;i--){cout<<i<<"  "<<LDS[i]<<"  "<<endl;}int ResultLen=indexLen;for (i=nLen;i>=0;i--){if(LDS[i]==ResultLen){index[ResultLen-1]=A[i];ResultLen--;}}for (i=0;i<indexLen;i++){cout<<index[i]<<" ";}delete []index;}int BiSearch(int *A,int nTarget,int nLen){assert(A!=NULL&&nLen>0);int start=0;int end=nLen-1;while (start<=end){int mid=(start+end)/2;if(nTarget>A[mid])end=mid-1;else if(nTarget<A[mid])start=mid+1;elsereturn mid;}return start;}int main(){int A[]={9,4,3,2,5,4,13,1};int nLen=sizeof(A)/sizeof(int);FindLongestSequence(A,nLen);return 1;}

题目:求两个串中的第一个最长子串(神州数码以前试题)。如"abractyeyt","dgdsaeactyey"的最大子串为"actyey"。

#include "stdafx.h"#include <iostream>#include <string>using namespace std;//两个串中的第一个最长子串string FindLongestCommonSubString(string strOne, string strTwo){    if ("" == strOne || strOne.length() <= 0 || "" == strTwo || strTwo.length() <= 0)    {        return NULL;    }    if (strOne.length() < strTwo.length())  //strOne始终是最长的, 相当于母串,strTwo相当于子串    {        string strTmp = strOne;        strOne = strTwo;        strTwo = strTmp;    }    int *mask = new int[strOne.length()];    int maxlength = 0;    int end = -1;    memset(mask, 0, sizeof(int)*strOne.length());    for (int i = 0; i < strTwo.length(); i++)    {        for (int j = strOne.length() - 1; j >= 0; j--)        {                if (strTwo[i] == strOne[j])            {                if (i == 0 || j == 0)                {                    mask[j] = 1; //母串为第一个元素,或者子串只有一个元素                }                else                {                    mask[j] = mask[j - 1] + 1;                }            }            else            {                mask[j] = 0;            }            if (mask[j] > maxlength)            {                maxlength = mask[j];                end = j;            }        }    }    delete [] mask;    return strOne.substr(end - maxlength + 1, maxlength);}int _tmain(int argc, _TCHAR* argv[]){    string strOne = "123456789abcdefghijklmn2131fdfdfdf";    string strTwo = "123456sdkk123456789abcddkfdfkd123456789abcde";    cout<<"第一个字符串: "<<strOne<<endl;    cout<<"第二个字符串: "<<strTwo<<endl;    cout<<"最长公共子串: "<<FindLongestCommonSubString(strOne, strTwo);    cout<<endl;    return 0;}

递归和非递归俩种方法实现二叉树的前序遍历。

2.非递归实现

       后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。下面介绍两种思路。

      第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。

void postOrder2(BinTree *root)    //非递归后序遍历{    stack<BTNode*> s;    BinTree *p=root;    BTNode *temp;    while(p!=NULL||!s.empty())    {        while(p!=NULL)              //沿左子树一直往下搜索,直至出现没有左子树的结点         {            BTNode *btn=(BTNode *)malloc(sizeof(BTNode));            btn->btnode=p;            btn->isFirst=true;            s.push(btn);            p=p->lchild;        }        if(!s.empty())        {            temp=s.top();            s.pop();            if(temp->isFirst==true)     //表示是第一次出现在栈顶              {                temp->isFirst=false;                s.push(temp);                p=temp->btnode->rchild;                }            else                        //第二次出现在栈顶              {                cout<<temp->btnode->data<<" ";                p=NULL;            }        }    }    }
 第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

void postOrder3(BinTree *root)     //非递归后序遍历{    stack<BinTree*> s;    BinTree *cur;                      //当前结点     BinTree *pre=NULL;                 //前一次访问的结点     s.push(root);    while(!s.empty())    {        cur=s.top();        if((cur->lchild==NULL&&cur->rchild==NULL)||           (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))        {            cout<<cur->data<<" ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过               s.pop();            pre=cur;         }        else        {            if(cur->rchild!=NULL)                s.push(cur->rchild);            if(cur->lchild!=NULL)                    s.push(cur->lchild);        }    }    }

二.中序遍历

    中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问

2.非递归实现

    根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,然后按相同的规则访问其右子树。因此其处理过程如下:

   对于任一结点P,

  1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;

  2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;

  3)直到P为NULL并且栈为空则遍历结束

void inOrder2(BinTree *root)      //非递归中序遍历{    stack<BinTree*> s;    BinTree *p=root;    while(p!=NULL||!s.empty())    {        while(p!=NULL)        {            s.push(p);            p=p->lchild;        }        if(!s.empty())        {            p=s.top();            cout<<p->data<<" ";            s.pop();            p=p->rchild;        }    }    }

大数字的存储问题:

问题描述:设计一个可以容纳40位数的求n! (n 的阶乘)的程序

代码:

void test5(){int n;cout<<"input n:"<<endl;cin>>n;int i,j,r;int data[40+1]={0};//从 1--->39//开始 1!data[1]=1;int digit=1;for(i=2;i<=n;i++){for(j=1;j<=digit;j++)data[j]*=i;r=0;for(j=1;j<=digit;j++){r=data[j]/10;data[j]=data[j]%10;if(r>0){data[j+1]=data[j+1]+r;if(j==digit){digit++;break;}r=0;}}}cout<<n<<"! = ";for(i=digit;i>=1;i--){cout<<data[i];}cout<<endl;}

const在c++/c的区别

在C语言中const表示只读的变量,既然把const看成变量,那么其在内存中就会有存储它的空间,并且可以通过指针间接的改变改内存空间的值

当通过指针p改变内存中的值后,在获取i的值的时候,会访问该空间,得到是被改变后的值

而在C++把const(内置类型)看做常量,编译器会使用常数直接替换掉对i的引用。并不会去访问i的内存地址去取数据

c++语言中知识对于内置数据类型做常数替换,而对于像结构体这样的非内置数据类型则不会。因为结构体类型不是内置数据类型,编译器不知道如何直接替换,访问内存空间。

在c++中,const定义的常量要具体情况具体对待:对于基本数据类型的常量,编译器会把它放到符号表中而不分配存储空间,而ADT/UDT的const对象则需要分配存储空间(大对象),还有一些情况下需要分配存储空间,例如强制声明为extern的符号常量或取符号常量的地址等操作。



 


 

 


0 0
原创粉丝点击