求1+2+3+…+n的值
题目描述:求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
题目分析:这道题什么也不能用,那直接加法就完了,不能for就递归呗。不用if的话就利用与的特性就好了。
需利用逻辑与的短路特性实现递归终止。 2.当n==0时,(n>0)&&((sum+=Sum_Solution(n-1))>0)只执行前面的判断,为false,然后直接返回0;
3.当n>0时,执行sum+=Sum_Solution(n-1),实现递归计算Sum_Solution(n)。
class Solution {
public:
int Sum_Solution(int n) {
int ans = n;
ans && (ans += Sum_Solution(n - 1));//当ans为0时就与为0,自动递归结束而不需要判断
return ans;
}
};
不用加减乘除做加法
题目描述:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
题目分析:
首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
class Solution {
public:
int Add(int num1, int num2)
{
while(num2!=0){
int temp=num1^num2;
num2=(num1&num2)<<1;
num1=temp;
}
return num1;
}
};
把字符串转化为整数
题目描述:将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
题目分析:很简单的题,没啥说的,情况考虑完就行了。数据上下 溢出,空字符串,只有正负号,有无正负号,错误标志输出
class Solution {
public:
bool IsShuzi(char k) {
if (k >= '0' && k <= '9') {
return true;
}
else { return false; }
}
int StrToInt(string str) {
vector<int>temp;
int first = 0;
int flag = 1;
if (str[0] == '+' ) {
first = 1;
}
if (str[0] == '-') {
first = 1;
flag = -1;
}
for (int i = first; i < str.length(); i++) {
if (IsShuzi(str[i]) == 0) {
return 0;
}
temp.push_back((int)(str[i] - '0'));
}
long output=0;
for (int i = 0; i < temp.size(); i++) {
int pre=output;
output += temp[i] * pow(10,(temp.size() - i-1));
}
if(output>0x7FFFFFFF && flag==1)return 0;
if(output>0x80000000 && flag==-1)return 0;
return output*flag;
}
};
数组中重复的数字
题目描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
题目分析:简单利用map性质即可。
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) {
if (length == 0)return false;
map<int,int>temp;
for (int i = 0; i < length; i++) {
temp[numbers[i]]++;
}
for (int i = 0; i < length; i++) {
if (temp[numbers[i]] > 1) {
*duplication = numbers[i];
return true;
}
}
return false;
}
};
当然这个题有一个牛逼的方法,非常的简单而且不需要额外的空间。
题目里写了数组里数字的范围保证在0 ~ n-1 之间,所以可以利用现有数组设置标志,当一个数字被访问过后,可以设置对应位上的数 + n,之后再遇到相同的数时,会发现对应位上的数已经大于等于n了,那么直接返回这个数即可。
int find_dup( int numbers[], int length) {
for ( int i= 0 ; i<length; i++) {
int index = numbers[i];
if (index >= length) { //如果大于值,就恢复原本的值
index -= length;
}
if (numbers[index] >= length) { //如果检测到原来的值发生了变化,那就说明出现了两次
return index;
}
numbers[index] = numbers[index] + length; //给对应的位加n
}
return - 1 ;
}
构建乘积数组
题目描述:给定一个数组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[i]的值可以看作下图的矩阵中每行的乘积。下三角用连乘可以很容求得,上三角,从下向上也是连乘。因此我们的思路就很清晰了,先算下三角中的连乘,即我们先算出B[i]中的一部分,然后倒过来按上三角中的分布规律,把另一部分也乘进去。
class Solution {
public:
vector<int> multiply(const vector<int>& A) {
int number = A.size();
vector<int>output(number);
vector<int>output1(number);
int temp1=1;
for (int i = 0; i < number; i++) {
output1[i] = temp1;
temp1 = temp1 * A[i];
}
vector<int>output2(number);
int temp2 = 1;
for (int i = number - 1; i >= 0; i--) {
output2[i] = temp2;
temp2 = temp2 * A[i];
}
for (int i = 0; i < number; i++) {
output[i] = output1[i] * output2[i];
}
return output;
}
};