牛客网剑指offer算法题打卡——day01
题1:求1+2+3+…+n
题目描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例:
输入
5
返回值
15
解析:
-
如题,如果要求1+2+3+…+n的累加,最普通的代码实现应该是:
int n = new Scanner(System.in).nextInt(); int sum = 0; for (int i = 0; i <= n; i++) { sum += i; }
-
在实现过程中必须满足
- 递增:让数字从1到n不断递增,实现逐位累加
- 终止:加到目标数字n即终止
-
但题目说明不能用循环以及乘除法,只能用其他方式实现”递增“与”终止“,那有什么其他方法实现这两种要素呢?
有的,递归和逻辑与
-
递归:
定义(条件):
(1)需要解决的问题可以转化为一个或者多个子问题来求解,而这些子问题的求解方法与原问题相同,只是在数量和规模上不同。
(2)递归的次数是有限的。
(3)必须有结束递归的条件来终止递归。
例子:
假设我们用递归来算阶乘 f(n):
f = n => n === 1 ? 1 : n * f(n-1)
f 里面用到了 f,怎么理解呢?
很简单,把式子展开即可:
f(6) => 6 * f(5) => 6 * (5 * f(4)) => 6 * (5 * (4 * f(3))) => 6 * (5 * (4 * (3 * f(2)))) => 6 * (5 * (4 * (3 * (2 * f(1))))) => 6 * (5 * (4 * (3 * (2 * 1)))) => 6 * (5 * (4 * (3 * 2))) => 6 * (5 * (4 * 6)) => 6 * (5 * 24) => 6 * 120 => 720
该例子来源知乎,侵删。
-
逻辑与:
定义:
符号为“&&”,只有两个操作数都是真,结果才是真。
"逻辑与"操作属于短路操作:
- 既如果第一个操作数能够决定结果,那么就不会对第二个操作数求值。
- 对于逻辑与操作而言,如果第一个操作数是假,则无论第二个操作数是什么值,结果都不可能是真,相当于短路了右边。
-
解答:
/*
解题思路:
利用 &&(逻辑与的短路)与递归的调用实现自增
*/
public int Sum_Solution(int n){
int sum = n;
boolean flag = (num > 0) && ((num += sum_solution(n - 1))>0);
return num;
}
题2:不用加减乘除做加法
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
示例:
输入
1,2
返回值
3
解析:
对于二进制的加法运算,若不考虑进位,
则1+1=0,1+0=1,0+1=1,0+0=0,通过对比异或,不难发现,此方法与异或运算类似。因而排出进位,加法可用异或来实现。
–然后考虑进位,0+0进位为0,1+0进位为1,0+1进位为0,1+1进位为1,该操作与位运算的&操作相似。
那么加法运算可以这样实现:
先不考虑进位,按位计算各位累加(用异或实现),得到值a;
然后在考虑进位,并将进位的值左移,得值b,若b为0,则a就是加法运算的结果,若b不为0,则a+b即得结果(递归调用该函数)。
解答:
-
public int add(int num1,int num2) { while(num2 != 0){ int temp = num1^num2;//相加各个位的值 异操作 num2 = (num1&num2)<<1;//相加进位的值 与操作 num1 = temp; } return num1; }
补充:
a^b 如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0
按位异或的3个特点:
- 00=0,01=1
0异或任何数==任何数
- 10=1,11=0
1异或任何数 == 任何数取反
- 任何数异或自己 == 把自己置0
异或的运用:
实现两个值的交换,而不必使用临时变量。
例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现: a = a^b; //a=10100111 b = b^a; //b=10100001 a = a^b; //a=00000110
快速判断两个值是否相等
举例1: 判断两个整数a,b是否相等,则可通过下列语句实现:
return ((a ^ b) == 0)
扩展:
不申请额外内存实现两个变量值得交换:
方法一:
通过异或来实现;
a=a^b;
b=a^b;
a=a^b;
方法二:
通过加减运算实现;
a=a+b;
b=a-b;
a=a-b;
申请额外内存实现两个变量值得交换:
方法一: 通过异或来实现; a=a^b; b=a^b; a=a^b; 方法二: 通过加减运算实现; a=a+b; b=a-b; a=a-b;