剑指offer第12题打印从1到n位数以及大整数加法乘法

 
 字符和数字加减就是字符的ASCII码和数字直接加减。
方法一:
1)在字符串操作中给一个整形数字加(字符0)就是把它转化为字符,当然给一个字符减去(字符0)就可以把它转化为数字了;如果确实是最后一位字符那仫就把该数字加1( 需要注意的是我们每次都是从最后一个字符开始加起)到这里我们就不得不考虑加法的进位了,只有当字符对应的数字加到10或者比10大时我们需要进位,否则就直接将该数字转化为字符存储到对应字符的位置中去; 在字符所转化的数字进位中不得不考虑的就是如果此时已经是第一个字符了那仫还需要进位吗?当然不需要否则就溢出了;当然如果是普通的情况我们就只需要将该位对应的数字减去10并将进位信号置为1可以了 ;
     2).如何输入呢?直接用printf?这就又掉入面试官的陷阱里去了这是面试官设置的第二个陷阱,我们知道在上述思路中当数字不够n位时我们是在前面几位补零,如果我们直接输出,那仫就把前面的零也一起输出了,这当然不符合我们的实际了, 所以这里也是值得我们注意的一个关键点;
 
 
 
 

方法二:将问题转换成数字排列

我们把问题换个思路考虑,会发现n位所有十进制数其实就是n个从0到9的全排列。也就是说,我们把数字的每一位都 从0到9排列一遍,就可以得到所有的十进制数。只是在打印的时候,排在数字前面的0不打印出来而已。

全排列用递归很容易表达,数字的每一位都可能是0~9中的一个数,然后设置下一位,递归结束的条件是我们已经设置好了数字的最后一位。

 

 

 大整数相乘

大整数加法运算:

注意进位就行,输入使用cin,注意最后一位可能进位,所以要对flag进行判断。

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<windows.h>
using namespace std;
#define SIZE 1000
int main1() {
    string s1, s2 , res;    
    cin >> s1 >> s2;
    int len1 = s1.size();
    int len2 = s2.size();
    reverse(s1.begin(),s1.end());
    reverse(s2.begin(), s2.end());
    //plus
    int len = min(len1, len2);
    int flag = 0;//进位
    int num1, num2,num3;
    for (int i = 0; i < len; ++i) {
        num1 = s1[i] - '0';//string to int
        num2 = s2[i] - '0';
        num3 = num1 + num2 + flag;
        if (num3 > 9) {
            flag = 1;
            num3 = num3 % 10;
        }
        else {
            flag = 0;
        }
        res.push_back(num3 + '0');
    }
    //find max len1 or len2
    if (len1 == len) {
        for (int i = len; i < len2; ++i) {
            num2 = s2[i] - '0';
            num3 = num2 + flag;
            if (num3 > 9) {
                flag = 1;
                num3 = num3 % 10;
            }
            else {
                flag = 0;
            }
            res.push_back(num3 + '0');
        }
    }

    if (len2 == len) {
        for (int i = len; i < len1; ++i) {
            num1 = s1[i] - '0';
            num3 = num1 + flag;
            if (num3 > 9) {
                flag = 1;
                num3 = num3 % 10;
            }
            else {
                flag = 0;
            }
            res.push_back(num3 + '0');
        }
    }
    if (len1 == len2 && flag == 1) {
        res.push_back(flag + '0');
    }
    reverse(res.begin(), res.end());
    cout << res << endl;
    return 0;
}
大整数加法

 大整数减法运算:

两个字符相减之后需要加上'0'之后才能变为字符,字符和数字直接加减是ASCII码的加减,例如b - 1等于a的ASCII码。

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
string sub1(string s1, string s2) {
    reverse(s1.begin(),s1.end());
    reverse(s2.begin(), s2.end());
    int len1 = s1.size();
    int len2 = s2.size();
    
    for (int i = 0; i < len2; ++i) {
        if (s1[i] >= s2[i]) {
            s1[i] = s1[i] - s2[i] + '0';
        }
        else {//需要借位
            s1[i] = 10 + s1[i] - s2[i] + '0';
            s1[i + 1] = s1[i + 1] - 1;//这里为什么不加上'0',因为前面加上'0'的本质是s1[i] - s2[i],
                                      //只有加上0这个字符的ASCII码才能获得对应的数字比如相减等于16,
                                      //加上0的ASCII码,得到字符16
        }                
    }
    cout << s1 << endl;
    for (int j = len2; j < len1; ++j) {
        if (s1[j] - '0' >= 0) {
            reverse(s1.begin(), s1.end());
            return s1;
        }
        else {
            s1[j] = 10 + s1[j];
            s1[j + 1] = s1[j + 1] - 1 ;
        }
    }
    reverse(s1.begin(), s1.end());
    return s1;
}
int main() {
    string s1, s2, res;
    cin >> s1 >> s2;
    //保证s1 > s2
    if (s1.size() < s2.size() || s1.size() == s2.size() && s1 < s2) {
        swap(s1, s2);
    }
    res = sub1(s1, s2);
    //cout << res << endl;
    int pos = res.find_first_not_of('0');
    res = res.substr(pos);
    cout << res << endl;
    system("pause");
    return 0;
    
}
大整数减法

 

 

 

posted @ 2017-10-12 23:15  zqlucky  阅读(358)  评论(0编辑  收藏  举报