剑指offer(六)其他

面试题9:斐波那契数列

题目:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39
举一反三:青蛙跳台阶;小矩形覆盖大矩形。

class Solution {
public:
    int Fibonacci(int n) {
        int num[n];
        num[0] = 0;
        num[1] = 1;
        for(int i=2; i<=n; i++){
            num[i] = num[i-2]+num[i-1];
        }
        return num[n];
    }
};

题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

class Solution {
public:
    int jumpFloor(int number) {
        int num[number];
        num[0] = 1;
        num[1] = 1;
        for(int i=2; i<=number; i++){
            num[i] = num[i-1]+num[i-2];
        }
        return num[number];
    }
};

题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
解题思路:得出规律f(n)=2的(n-1)次方。

class Solution {
public:
    int jumpFloorII(int number) {
        int num[number];
        num[1] = 1;
        for(int i=2; i<=number; i++){
            num[i] = 2*num[i-1];
        }
        return num[number];
    }
};

题目:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
解题思路:斐波那契数列

class Solution {
public:
    int rectCover(int number) {
        if(number <= 0)
            return 0;
        if(number == 1)
            return 1;
        if(number ==2)
            return 2;
        int sum, num1=1, num2 = 2;
        for(int i=3;i<=number;i++){
            sum = num1+num2;
            num1 = num2;
            num2 = sum;
        }
        return sum;
    }
};

面试题10:二进制中1的个数

题目:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
解题思路:第一种方法是该数和1相与后右移一位,但是无法解决负数问题;第二种方法是该数和1相与后,1左移一位,循环次数就是该数的二进制位数;第三种方法是该数和(该数减1)相与,那么该数的二进制中最右边的1变成0其他位数不变,循环次数就是该数二进制中1的个数,此法最佳。
举一反三:用一条语句判断一个整数是不是2的整数次方(如果是的话,它的二进制表示有且只有1位是1)。计算需要改变m的二进制数中的多少位才能得到n(先异或,再统计异或结果中1 的位数)。

class Solution {
public:
     int  NumberOf1(int n) {
         int count = 0;
         while(n){
             count++;
             n = (n-1) & n;
         }
         return count;
     }
};

面试题11:数值的整数次方

题目:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
解题思路:两个情况需要考虑到,一是base为0,exponent<0时,返回0,用全局变量g_InvalidInput提示;二是base非0,exponent<0时,对正数时的它求导数即可。

class Solution {
public:
    bool g_InvalidInput = false;
    double Power(double base, int exponent) {
        if(equal(base,0.0) && exponent<0){
            g_InvalidInput = true;
            return 0.0;
        }
        int absExponent = exponent;
        if(exponent<0)
            absExponent = -exponent;
        double res = powerWithUnsignedExponent(base, absExponent);
        if(exponent<0)
            res = 1.0/res;
        return res;
    }
    bool equal(double num1, double num2){
        if((num1 - num2 < 0.0000001) && (num1 - num2 > -0.0000001))
            return true;
        else
            return false;
    }
    double powerWithUnsignedExponent(double base, int exponent){
        if(exponent == 0)
            return 1;
        if(exponent == 1)
            return base;
        double result = powerWithUnsignedExponent(base, exponent>>1);
        result *= result;
        if(exponent & 0x1 == 1)
            result *= base;
        return result;
    }
};

面试题20:顺时针打印矩阵

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
解题思路:要注意中间maxCol和minCol、maxRow和minRow的大小判断,以防剩下一列和一行的情况。

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int> result;
        int rows = matrix.size();
        int columns = matrix[0].size();
        int minRow = 0, maxRow = rows-1, minCol = 0, maxCol = columns-1;
        int curRow, curCol;
        while(minRow<=maxRow && minCol<=maxCol){
            for(curRow = minRow, curCol = minCol; curCol <= maxCol; curCol++){
                result.push_back(matrix[curRow][curCol]);
            }
            minRow++;
            for(curRow = minRow, curCol = maxCol; curRow <= maxRow; curRow++){
                result.push_back(matrix[curRow][curCol]);
            }
            maxCol--;
            if(maxCol < minCol || maxRow < minRow)
                break;
            for(curRow = maxRow, curCol = maxCol; curCol >= minCol; curCol--){
                result.push_back(matrix[curRow][curCol]);
            }
            maxRow--;
            for(curRow = maxRow, curCol = minCol; curRow >= minRow; curRow--){
                result.push_back(matrix[curRow][curCol]);
            }
            minCol++;
        }
        return result;
    }
};

面试题32:从1到n整数中1出现的次数

题目:输入一个整数n,求从1到n这n个整数的十进制中1出现的次数。
解题思路:把数分成两部分,对前部分递归计算,对后部分直接计算。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n <= 0)
            return 0;
        char str[50];
        sprintf(str,"%d",n);
        return numberOf1(str);
    }
    int numberOf1(const char* str){
        if(!str || *str=='\0' || *str<'0' || *str>'9')
            return 0;
        //假设str是“21345”
        int firstNum = *str - '0';  //firstNum=2
        int length = strlen(str);
        if(length==1 && firstNum==0) //终止条件是length=1
            return 0;
        if(length==1 && firstNum>0)
            return 1;
        int firstDigit = 0;
        //firstDigit保存1345-21345之间最高为1的数的数目
        if(firstNum > 1)
            firstDigit = powerBase10(length-1);
        else if(firstNum == 1)
            firstDigit = atoi(str+1)+1;
        //OtherDigits保存1345-21345之间后4位出现1的数的数目:2*4*1000
        int OtherDigits = firstNum * (length-1) * powerBase10(length-2);
        //recursive保存1-1345之间出现1的数目,递归
        int recursive = numberOf1(str+1);
        //三数相加
        return firstDigit+OtherDigits+recursive;
    }
    int powerBase10(int n){
        int result = 1;
        while(n--)
            result *= 10;
        return result;
    }
};

面试题34:丑数

题目:把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
解题思路:寻找规律以避免对非丑数的计算。新的丑数来自于旧的丑数乘以2/3/5,所以用一个辅助数组保存已经计算出的丑数,将其乘以2/3/5,分别求出比已有最大丑数M大但又最接近M的数:M2/M3/M5,再求其中最小的一个,就是下一个丑数。这个方法以空间消耗换取时间效率的提升。

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index<=0)
            return 0;
        int uglyNumbers[index];
        uglyNumbers[0] = 1;
        int *M2 = uglyNumbers;
        int *M3 = uglyNumbers;
        int *M5 = uglyNumbers;
        int uglyIndex = 1;
        while(uglyIndex < index){
            int minNum = Min(*M2 * 2, *M3 * 3, *M5 * 5);
            uglyNumbers[uglyIndex++] = minNum;
            while(*M2 * 2 <= minNum)
                M2++;
            while(*M3 * 3 <= minNum)
                M3++;
            while(*M5 * 5 <= minNum)
                M5++;
        }
        int result = uglyNumbers[uglyIndex-1];
        return result;
    }
    int Min(int a,int b,int c){
        int min = (a < b) ? a : b;
        return (min < c) ? min : c;
    }
};

面试题41:和为S的连续正数序列

题目:输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
解题思路:两个指针从头出发,若小于sum则right向前走一步,若大于sum则left向前走一步,若等于sum则添加到vector中接着让right向前走一步,停止条件是left走到(sum+1)/2.

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int>> result;
        if(sum < 3)
            return result;
        int left = 1;
        int right = 2;
        int curSum = left + right;
        while(left < (sum+1)/2){
            if(curSum < sum){
                right++;
                curSum += right;
            }else if(curSum > sum){
                curSum -= left;
                left++;
            }else{
                vector<int> tmp;
                for(int i=left;i<=right;i++){
                    tmp.push_back(i);
                }
                result.push_back(tmp);
                right++;
                curSum += right;
            }
        }
        return result;
    }
};

题目:输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。对应每个测试案例,输出两个数,小的先输出。
解题思路:两个指针一头一尾出发。

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        vector<int> result;
        int len = array.size();
        if(len > 1){
            int left = 0;
            int right = len-1;
            while(left < right){
                int curSum = array[left] + array[right];
                if(curSum == sum){
                    result.push_back(array[left]);
                    result.push_back(array[right]);
                    break;
                }else if(curSum > sum){
                    right--;
                }else{
                    left++;
                }
            }
        }
        return result;
    }
};

面试题44:扑克牌的顺子

题目:从扑克牌中随机抽几张牌,判断是不是一个顺子。2-10为本身,A为1,J为11,Q为12,K为13,大小王可以看成任意数字(在输入中0代表大小王)。
解题思路:先排序,统计数组中0的个数,最后统计排序后的数组中相邻数字之间的空缺总数。如果空缺总数小于或者等于0的个数,那么这个数组就是连续的,反之则不连续。

class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        int len = numbers.size();
        if(len==0)
            return false;
        sort(numbers.begin(),numbers.end());
        int numOfZero = 0;
        for(int i=0;i<len;i++)
            if(numbers[i] == 0)
                numOfZero++;
        int numOfGap = 0;
        int small = numOfZero;
        int big = small + 1;
        while(big<len){
            if(numbers[small] == numbers[big])
                return false;
            numOfGap += numbers[big] - numbers[small] - 1;
            small++;
            big++;
        }
        return (numOfZero >= numOfGap ? true : false);
    }
};

面试题45:圆圈中最后剩下的数字

题目:0,1,…,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
解题思路:最直观的想法就是用环形列表来实现。但是时间复杂度有O(mn),空间复杂度有O(n)。最好的办法是寻找数学规律,就会变得很简单。

class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n<1 || m<1)
            return -1;
        list<int> nums;
        for(int i=0;i<n;i++)
            nums.push_back(i);
        list<int>::iterator cur = nums.begin();
        while(nums.size() > 1){
            for(int i=1;i<m;i++){
                cur++;
                if(cur == nums.end())
                    cur = nums.begin();
            }
            list<int>::iterator next = ++cur;
            if(next == nums.end())
                next = nums.begin();
            nums.erase(--cur);
            cur = next;
        }
        return *cur;
    }
};
//下面这个更好
class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n<1 || m<1)
            return -1;
        int last = 0;
        for(int i=2; i<=n; i++){
            last = (last + m) % i;
        }
        return last;
    }
};

面试题46:求1+2+3+…+n

题目:求1+2+3+…+n。要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句。

//用n>0的&&来代替终止判断。
class Solution {
public:
    int Sum_Solution(int n) {
        int sum = n;
        bool ans = (n>0)&&((sum+=Sum_Solution(n-1))>0);
        return sum;
    }
};
//利用函数指针求解
typedef int (*fun)(int);
class Solution {
public:
    static int Solution_Terminator(int n){
        return 0;
    }
    static int Sum_Solution(int n) {
        static fun f[2] = {Solution_Terminator,Sum_Solution};
        return n+f[!!n](n-1);
    }
};

面试题47:不用加减乘除做加法

题目:求两个整数之和。要求在函数体内不得使用+、-、*、/ 四则运算符号。
解题思路:首先想到位运算,然后经过分析可以发现是位异或、位相与再左移一位的结果的和。

class Solution {
public:
    int Add(int num1, int num2)
    {
        int sum,carry;
        do{
            sum = num1 ^ num2;
            carry = (num1 & num2) << 1;
            num1 = sum;
            num2 = carry;
        }while(num2 != 0);
        return num1;
    }
};

面试题49:把字符串转换成整数

题目:将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
解题思路:看似简单的题目,但是需要考虑很多特殊情况,比如是否为空、正负号、非法溢出、非法字符(除0到9之外的数字)的处理。

class Solution {
public:
    int StrToInt(string str) {
        int len = str.length();
        if(len == 0)
            return 0;
        long num = 0;
        int flag = 1;
        int i = 0;
        while(str[i] == ' ') //过滤前面的空格
            i++;
        if(str[i] == '+') //处理正负号
            i++;
        else if(str[i] == '-'){
            i++;
            flag = -1;
        }
        while(str[i] != '\0'){
            if(str[i]>='0' && str[i]<='9'){
                num = num * 10 + flag *(str[i] - '0');
                if((flag==1 && num>0x7fffffff) || (flag==-1 && num<(signed int)0x80000000)){ //处理溢出
                    num = 0;
                    break;
                }
                i++;
            }else{ //处理非法字符
                num = 0;
                break;
            }
        }
        return num;
    }
};

面试题53:正则表达式匹配

题目:请实现一个函数用来匹配包括’.’和’‘的正则表达式。模式中的字符’.’表示任意一个字符,而’‘表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串”aaa”与模式”a.a”和”ab*ac*a”匹配,但是与”aa.a”和”ab*a”均不匹配
解题思路:最直观的两个匹配情况是:str中的字符和pattern中的字符是同种字符;pattern中的字符是’.’,str中的字符可以任意。复杂的是pattern字符是’‘,画一个状态机就可以知道,有三种匹配模式:str的字符和pattern’‘前面的字符不匹配,pattern向后移动两个字符;str的字符和pattern’‘前面的字符匹配,str向后移动一个字符,pattern向后移动两个字符;str的字符和pattern’‘前面的字符匹配,str向后移动一个字符,pattern不移动。停止条件是:如果str和pattern同时到达末尾,则模式匹配成功;如果str没有到达末尾,而pattern到达末尾,则模式匹配失败。

class Solution {
public:
    bool match(char* str, char* pattern)
    {
        if(str == NULL || pattern == NULL)
            return NULL;
        return matchCore(str,pattern);
    }
    bool matchCore(char* str,char* pattern){
        if(*str == '\0' && *pattern == '\0')
            return true;
        if(*str != '\0' && *pattern == '\0')
            return false;
        if(*(pattern+1) == '*'){
            if(*pattern == *str || (*pattern=='.'&&*str!='\0'))
                return (matchCore(str+1,pattern+2) || matchCore(str+1,pattern) || matchCore(str,pattern+2));
            else
                return matchCore(str,pattern+2);
        }
        if(*str == *pattern || (*pattern == '.' && *str != '\0'))
            return matchCore(str+1, pattern+1);
        return false;
    }
};

面试题64:数据流中的中位数

题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
解题思路:首先要确定用什么数据结构来定义存放数据的数据容器,需要考虑插入和查找的时间复杂度。经过对数组、链表、二叉搜索树、AVL树的分析,插入最少需要O(log n)时间,查找最少需要O(1),但是AVL数的实现较复杂,所以想到用一个最小堆和一个最大堆来实现。接下来是实现的细节,首先需要保证数据平均分配到两个堆中,因此两个堆中的数目之差不能超过1,可以在当前数据的总数目为偶数时,将数据插入到最小堆中,为奇数时,插入到最大堆中。但是还要保证最大堆中的数据都比最小堆中的数据来得小,插入时怎么保证这一点,可以先把数据插入到最大堆中,再把最大堆中最大的数据拿出来插入最小堆中。奇数时也是类似。

class Solution {
public:
    void Insert(int num)
    {
        if(((min.size()+max.size()) & 1) == 0){ //当前数据总数目是偶数
            if(max.size()>0 && num < max[0]){
                max.push_back(num);
                push_heap(max.begin(),max.end(),less<int>());
                num = max[0];
                pop_heap(max.begin(),max.end(),less<int>());
                max.pop_back();
            }
            min.push_back(num);
            push_heap(min.begin(),min.end(),greater<int>());
        }else{
            if(min.size()>0 && num > min[0]){
                min.push_back(num);
                push_heap(min.begin(),min.end(),greater<int>());
                num = min[0];
                pop_heap(min.begin(),min.end(),greater<int>());
                min.pop_back();
            }
            max.push_back(num);
            push_heap(max.begin(),max.end(),less<int>());
        }
    }

    double GetMedian()
    { 
        int size = min.size() + max.size();
        //if(size == 0)
            //throw exception("No numbers are available");
        double median;
        if((size & 1) == 0)
            median = (min[0] + max[0])/2.0;
        else
            median = min[0];
        return median;
    }
private:
    vector<int> min;
    vector<int> max;
};

面试题65:滑动窗口的最大值

题目:给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
解题思路:如果采用蛮力法,每个窗口需要O(k)的时间才能找出滑动窗口里的最大值,对于长度为n的输入数组,总的时间复杂度为O(nk)。可以把一个滑动窗口看成是一个两端开口的队列,只把有可能成为滑动窗口最大值的数值存入到这个两端开口的队列(deque)中。

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> max;
        deque<int> index;
        if(num.size() >= size && size >= 1){
            for(unsigned int i=0; i<num.size(); i++){
                while(index.size() && num[i] >= num[index.back()])//把队列中所有比待输入的数字num小的数字都弹出
                    index.pop_back();
                if(index.size() && (i-index.front()+1)>size) //判断队首的数字有没有超过滑窗的大小
                    index.pop_front();
                index.push_back(i);
                if(size&&i+1>= size) 滑动到第size个num才开始放入结果
                    max.push_back(num[index.front()]);
            }
        }
        return max;
    }
};

面试题66:矩阵中的路径

题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串”bcced”的路径,但是矩阵中不包含”abcb”路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
解题思路:这是个用回溯法解决的典型题。由于回溯法递归的特性,路径可以被看成是一个栈,当在矩阵中定位了路径中前n个字符的位置之后,在第n个字符的周围寻找第n+1个字符,若没有则回到第n-1个字符重新定位第n个字符。路径的起点可以是矩阵中的任一点。由于路径不能重复进入矩阵的格子,还需要定义和字符矩阵大小一样的布尔值矩阵,用于标识路径是否已经进入了每个格子。

class Solution {
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {
        if(matrix == NULL || rows<1 || cols<1 || str==NULL)
            return false;
        bool *visited = new bool[rows * cols];
        memset(visited,0,rows*cols);

        int pathLength = 0;
        for(int row=0;row<rows;row++){
            for(int col=0;col<cols;col++){
                if(hasPathCore(matrix,rows,cols,row,col,str,pathLength,visited))
                    return true;
            }
        }
        delete[] visited;
        return false;
    }
    bool hasPathCore(char* matrix,int rows,int cols,int row,int col,char* str,int &pathLength,bool* visited){
        if(str[pathLength] == '\0')
            return true;
        bool hasPath = false;
        if(row>=0 && row<rows && col>=0 && col<cols && matrix[row*cols+col]==str[pathLength] && !visited[row*cols+col]){
            pathLength++;
            visited[row*cols+col] = true;
            hasPath = hasPathCore(matrix,rows,cols,row,col-1,str,pathLength,visited) ||
                hasPathCore(matrix,rows,cols,row,col+1,str,pathLength,visited) ||
                hasPathCore(matrix,rows,cols,row+1,col,str,pathLength,visited) ||
                hasPathCore(matrix,rows,cols,row-1,col,str,pathLength,visited);
            if(!hasPath){
                pathLength--;
                visited[row*cols+col] = false;
            }
        }
        return hasPath;
    }
};

面试题67:机器人的运动范围

题目:地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解题思路:用的也是回溯法,机器人从坐标(0,0)开始移动,当它准备进入到坐标为(i,j)的格子时,通过检查坐标的数位和来判断机器人能否进入,如果机器人能够进入坐标为(i,j)的格子,再接着判断它能否进入四个相邻的格子。

class Solution {
public:
    int movingCount(int threshold, int rows, int cols)
    {
        bool *visited = new bool[rows*cols];//标识这个格子是否已经进过了
        memset(visited,0,rows*cols);
        int count = movingCountCore(threshold,rows,cols,0,0,visited);//从原点出发
        delete[] visited;
        return count;
    }
    int movingCountCore(int threshold,int rows,int cols,int row,int col,bool* visited){
        int count = 0;
        if(check(threshold,rows,cols,row,col,visited)){ //check函数判断机器人能否进入坐标为(row,col)的格子
            visited[row*cols+col] = true;
            count = 1+movingCountCore(threshold,rows,cols,row+1,col,visited)+
                movingCountCore(threshold,rows,cols,row-1,col,visited)+
                movingCountCore(threshold,rows,cols,row,col+1,visited)+
                movingCountCore(threshold,rows,cols,row,col-1,visited);
        }
        return count;
    }
    bool check(int threshold,int rows,int cols,int row,int col,bool* visited){
        if(row>=0 && row<rows && col>=0 && col<cols && 
           getDigitSum(row)+getDigitSum(col)<=threshold && !visited[row*cols+col])
            return true;
        return false;
    }
    int getDigitSum(int num){  //getDigitSum用来你得到一个数字的数位之和
        int sum = 0;
        while(num>0){
            sum += num%10;
            num /= 10;
        }
        return sum;
    }
};
阅读更多
换一批

没有更多推荐了,返回首页