剑指offer题解11

48 数组中重复的数

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

分析:想使用标记法,但是如果不使用额外空间,0不好处理,那么就是用交换好了,把数字放在该在的位置,如果发现该位置已经有了正确的数字,那么就找到了重复的数字


public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if(numbers==null){
            return false;
        }
        for(int i=0;i<numbers.length;i++){
            while(numbers[i]!=i&&numbers[i]!=numbers[numbers[i]]){
                swap(numbers,i,numbers[i]);
            }
            if(numbers[i]==numbers[numbers[i]]&&i!=numbers[i]){
                duplication[0]=numbers[i];
                return true;
            }
        }
        return false;
        
    }
    private void swap(int[] nums,int i,int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }   
}

49 构建乘积数组

题目描述
给定一个数组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]。不能使用除法。

分析:第一想法就是计算说有的乘积,然后除以这个数,但是不能使用出发,因此可以先从左边计算(缺失右边),再从右边计算(补充右边)

import java.util.Arrays;
public class Solution {
    public int[] multiply(int[] A) {
        int[] res=new int[A.length];
        Arrays.fill(res,1);
        int sum=1;
        for(int i=1;i<res.length;i++){
            sum*=A[i-1];
            res[i]=sum;
        }
        sum=1;
        for(int i=res.length-2;i>=0;i--){
            sum*=A[i+1];
            res[i]*=sum;
        }
        return res;
    }
}

50 正则表达式匹配

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

分析:
考虑特殊情况,有一个为空,或者都为空,返回false

假如pattern中的下一个字符是,那么有四种情况:*
str当前的字符与当前pattern中的字符匹配:

  1. *表示为匹配的个数为0,patternIndex+=2,
  2. *表示匹配个数为1,patternIndex+=2,strIndex+=1
  3. *表示匹配个数为多个,strIndex+=1
    str当前的字符与当前pattern中的字符不匹配:参照上述第一条

如果pattern下一个字符不是,那么只有一种情况*:匹配成功或者失败

public class Solution {
    public boolean match(char[] str, char[] pattern) {
        if(str==null||pattern==null){
            return false;
        }
        int strIndex=0,patternIndex=0;
        boolean res=myMatch(str,pattern,strIndex,patternIndex);

        return res;
    }

    private boolean myMatch(char[] str, char[] pattern, int strIndex, int patternIndex) {
        //同时结束
        if(strIndex==str.length&&patternIndex==pattern.length){
            return true;
        }
        //patternIndex先结束
        if(patternIndex==pattern.length){
            return false;
        }

        //下一位是*
        if (patternIndex+1<pattern.length&&pattern[patternIndex+1]=='*'){
            //1. *0
            //2. *1
            //3. *n
            //此时可能str已经结束,而pattern还没有结束
            if(strIndex!=str.length&&(str[strIndex]==pattern[patternIndex]||pattern[patternIndex]=='.')){
                return myMatch(str,pattern,strIndex,patternIndex+2)
                        ||myMatch(str,pattern,strIndex+1,patternIndex+2)
                        ||myMatch(str,pattern,strIndex+1,patternIndex);
            }else {
                //不匹配,可以认为pattern匹配为0
                return myMatch(str,pattern,strIndex,patternIndex+2);
            }
        }

        //下一位不是*
        if (strIndex!=str.length&&(pattern[patternIndex]=='.'||str[strIndex]==pattern[patternIndex])){
            return myMatch(str,pattern,strIndex+1,patternIndex+1);
        }
        return false;

    }
}


51 表示字符的字符串

题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

分析:判断小数点,E,正负号是否合法即可

public class Solution {
    public boolean isNumeric(char[] str) {
        //防御
        if(str==null||str.length==0){
            return false;
        }
        boolean hasE=false,decimal=false,sign=false;
        for(int i=0;i<str.length;i++){
            //处理e
            if(str[i]=='e'||str[i]=='E'){
                //e后有数字
                if(i==str.length-1){
                    return false;
                }
                //e只能出现一次
                if(hasE){
                    return false;
                }
                hasE=true;
            }
            //处理sign
            else if(str[i]=='+'||str[i]=='-'){
                //第二次出现符号
                if(sign&&str[i-1]!='e'&&str[i-1]!='E'){
                    return false;
                }
                //第一次出现符号
                if(!sign && i>0 && str[i-1]!='e'&&str[i-1]!='E'){
                    return false;
                }
            }
            //处理小数点
            else if(str[i]=='.'){
                //小数点不能出现在E后,也不能出现两次
                if(hasE||decimal){
                    return false;
                }
                decimal=true;
            }
            //处理不合法字符
            else if(str[i]<'0'||str[i]>'9'){
                return false;
            }
        }
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/gentlezuo/article/details/91345589