剑指offer(49~51)把字符串转换成整数--数组中重复的数字--构建乘积数组

文章目录

  • 把字符串转换成整数
  • 数组中重复的数字
  • 构建乘积数组

把字符串转换成整数

将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。

注意两点:

  1. 第一个字符是正负号也是合法的。
  2. 如果只输入一个字符0,也应该是合法的,对于不合法输入和合法输入字符0,需要区分。
class Solution {
public:
    int StrToInt(string str) {
        int strLen = str.size();
        if(strLen <= 0) {
            return 0;
        }
        int symbol = 1;
        if(str[0]=='-') {
            symbol = symbol * -1;
        }
        int res = 0;
        for(int i = (str[0] == '+' || str[0] == '-')? 1 : 0;i<strLen; ++i) {
            if(str[i] >= '0' && str[i] <= '9') 
            {
                int tmp = str[i] - '0';
                if(symbol > 0 && res >= INT_MAX/10 && tmp > INT_MAX%10){
                    return 0;
                }
                else if(symbol < 0 && -res <= INT_MIN/10 &&-tmp < INT_MIN % 10) {
                    return 0;
                }
                res = res * 10 + tmp;
            }
            else {
                return 0;
            }
        }
        return res * symbol;
    }
};    

牛客网链接

数组中重复的数字

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

对于关联式容器map或者set来讲,重复的数值是会插入失败的,那么一旦插入失败,就遇到了第一个重复的数字,使用unordered_set效率很更高。

class Solution {
public:
	// Parameters:
	//        numbers:     an array of integers
	//        length:      the length of array numbers
	//        duplication: (Output) the duplicated number in the array number
	// Return value:       true if the input is valid, and there are some duplications in the array number
	//                     otherwise false
	bool duplicate(int numbers[], int length, int* duplication) {
			unordered_set<int> myset;
			for (int i = 0; i < length; ++i)
			{
                if(number[i]<0||number[i]>length-1)
                    return false;
				if (!(myset.insert(numbers[i])).second)
				{
					cout << numbers[i] << endl;
					*duplication = numbers[i];
					return true;
				}
			}
			return false;
	}
};

上述代码时间复杂度是 O ( n ) O(n) O(n),需要付出的代价是要一个空间是 O ( n ) O(n) O(n)的哈希表。实际上还有更优的算法,省掉这个哈希表所占的空间。仔细想想对于这个数组而言,所有元素都在0到n-1之间,那么如果不存在重复的数,每个元素都存在和自己相等的下标,那么我们可以在进行排序的同时去判断是否存在重复的数。

class Solution {
public:
	// Parameters:
	//        numbers:     an array of integers
	//        length:      the length of array numbers
	//        duplication: (Output) the duplicated number in the array number
	// Return value:       true if the input is valid, and there are some duplications in the array number
	//                     otherwise false
	bool duplicate(int numbers[], int length, int* duplication) {
			for (int i = 0; i < length; ++i)
			{
                if(numbers[i]<0||numbers[i]>length-1)
                    return false;
				if(numbers[i]!=i)
                {
                    if(numbers[i]==numbers[numbers[i]])
                    {
                        *duplication=numbers[i];
                        return true;
                    }
                    swap(numbers[i],numbers[numbers[i]]);
                }
                else
                    i++;
			}
			return false;
	}
};

牛客网链接

构建乘积数组

给定一个数组 A [ 0 , 1 , . . . , n − 1 ] A[0,1,...,n-1] A[0,1,...,n1],请构建一个数组 B [ 0 , 1 , . . . , n − 1 ] B[0,1,...,n-1] B[0,1,...,n1],其中B中的元素 B [ i ] = A [ 0 ] ∗ A [ 1 ] ∗ . . . ∗ A [ i − 1 ] ∗ A [ i + 1 ] ∗ . . . ∗ A [ n − 1 ] B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1] B[i]=A[0]A[1]...A[i1]A[i+1]...A[n1]。不能使用除法。

B和A长度相等,对于B而言,可分两段,前半段是A[0]+A[1]+…+A[i-1],后半段A[i+1]+A[i+2]+…+A[n-1]。

class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        int len=A.size();
        vector<int> B;
        B.resize(len);
        
        for(int i=0;i<len;i++)
            B[i]=GetB(A,i,len);
        return B;
    }
    int GetB(const vector<int>& A,int i,int len)
    {
        int b=1;
        for(int index=0;index<i;index++)
            b*=A[index];
        for(int index=i+1;index<len;index++)
            b*=A[index];
        return b;
    }
};

仔细想想这个时间复杂度是 O ( n 2 ) O(n^2) O(n2),实际上我们做了很多重复的运算,我们再看看这个B数组。
剑指offer(49~51)把字符串转换成整数--数组中重复的数字--构建乘积数组_第1张图片
假设前半段自上向下看,设为 C [ i ] = C [ i − 1 ] ∗ A [ i − 1 ] C[i]=C[i-1]*A[i-1] C[i]=C[i1]A[i1],而后半段自下向上看,假设为 D [ i ] = D [ i + 1 ] ∗ A [ i + 1 ] D[i]=D[i+1]*A[i+1] D[i]=D[i+1]A[i+1]。在实际上代码中,我们不需要定义多个数组,只需要一个B数组即可。

class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        int len=A.size();
        vector<int> B(len,0);
        
        B[0]=1;//上例的C的第0个元素
        for(int i=1;i<len;i++)
        {
            B[i]=B[i-1]*A[i-1];
        }
        
        double tmp=1;//倒数第一个D是1
        for(int i=len-2;i>=0;i--)
        {
            tmp*=A[i+1];
            B[i]*=tmp;
        }
        
        return B;
    }
};

牛客网链接

你可能感兴趣的:(剑指offer)