剑指offer47-52

47 求1+2+3…+n

题目描述

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

示例1

输入:

5

返回值:

15

思路:

题目限制不能使用乘除法和条件判断语句,所以只能使用递归来计算

class Solution {
public:
    int Sum_Solution(int n) {
        if(n==1)return n;
        return n+Sum_Solution(n-1);
    }
};

48 不用加减乘除做加法

题目描述

写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

示例1

输入:

1,2

返回值:

3

思路:

不能用四则运算符号,所以要使用位运算。

两个整数&运算,等于1的位需要向前进一位,两个整数^运算,等于1的是不需要进位的位

把进位后的数和不需要进位的数再次&运算,循环执行直到没有需要进位的位

class Solution {
public:
    int Add(int num1, int num2) {
        while(num2){
            int t=(num1&num2)<<1;
            num1=num1^num2;
            num2=t;
        }
        return num1;
    }
};

49 把字符串转换成整数

题目描述

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

示例1

输入:

"+2147483647"

返回值:

2147483647

思路:

设置一个标志位判断该整数时正数还是负数

循坏判断每一个字符是否在’0’到’9’之间,若不在范围内则不合法,若在范围内减去’0’就是int类型对应的数

class Solution {
public:
    int StrToInt(string str) {
        int flag=0;
        if(str.size()==0)return 0;
        if(str[0]=='-')flag=-1;
        else if(str[0]=='+')flag=1;
        int i,num=0;
        if(flag==0){
            i=0;
            flag=1;
        }
        else i=1;
        for(i;i<str.size();i++){
            if(str[i]>'9'||str[i]<'0')return 0;
            int t=str[i]-'0';
            num=num*10+t;
        }
        return num*flag;
    }
};

50 数组中重复的数字

题目描述

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是第一个重复的数字2。没有重复的数字返回-1。

示例1

输入:

[2,3,1,0,2,5,3]

返回值:

2

思路:

利用位于算记录每个数出现的次数,遇上第一个重复出现的数之间返回结果

class Solution {
public:
    int duplicate(vector<int>& numbers) {
        int n=0;
        for(int i=0;i<numbers.size();i++){
            if(n&(1<<numbers[i]))return numbers[i];
            n|=1<<numbers[i];
        }
        return -1;
    }
};

51 构建乘积数组

题目描述

给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * … * A[n-1],B[n-1] = A[0] * A[1] * … * A[n-2];)

对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。

示例1

输入:

[1,2,3,4,5]

返回值:

[120,60,40,30,24]

思路:
在这里插入图片描述

先计算下三角的积,B[n]=B[n-1]*A[n-1]

再计算上三角的积,temp*=A[n+1]

B[n]*=temp

class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        int length=A.size();
        vector<int> B(length,1);
        for(int i=1;i<length;i++){
            B[i]=B[i-1]*A[i-1];
        }
        int temp=1;
        for(int i=length-2;i>=0;i--){
            temp*=A[i+1];
            B[i]*=temp;
        }
        return B;
    }
};

52 正则表达式匹配

题目描述

请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配

示例1

输入:

"aaa","a*a"

返回值:

true

思路:

利用动态规划的思想,dp[i] [j]表示s的前i个字符和p的前j个字符匹配,dp[i] [j]的取值分为以下几种情况

  1. s[i]==p[j]||p[j]==’.'意思时s和p当前字符匹配,此时dp[i] [j]=dp[i-1] [j-1]
  2. s和p当前字符不匹配但p[j]==’*'此时需要注意p[j-1]是否与s[i]匹配,若匹配dp[i] [j]=dp[i] [j-1]也可能是dp[i] [j]=dp[i] [j-2],若*匹配了多个字符,则可以看成划掉s当前字符,去s[i-1]去和p[j]匹配,即dp[i] [j]=dp[i-1] [j]
  3. 若p[j]==’*'且p[j-1]与s[i]不匹配,则dp[i] [j]=dp[i] [j-2]
  4. 若p[j]位字符,且与s[i]不匹配,dp[i] [j]==false

首先初始化s为空串的情况,再从s的首位开始匹配

class Solution {
public:
    bool match(string str, string pattern) {
        int len1=str.size(),len2=pattern.size();
        vector<vector<bool>> dp(len1+1,vector<bool>(len2+1,false));
        dp[0][0]=true;
        for(int j=1;j<=len2;j++){
            if(pattern[j-1]=='*')dp[0][j]=dp[0][j-2];
        }
        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                if(pattern[j-1]==str[i-1]||pattern[j-1]=='.'){
                    dp[i][j]=dp[i-1][j-1];
                }
                else if(pattern[j-1]=='*'){
                    if(pattern[j-2]==str[i-1]||pattern[j-2]=='.'){
                        dp[i][j]=dp[i][j-2]||dp[i][j-1]||dp[i-1][j];
                    }
                    else{
                        dp[i][j]=dp[i][j-2];
                    }
                }
            }
        }
        return dp[len1][len2];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值