1.不用加减乘除做加法
思路: 1.不进位加法:异或 a^b
2.进位加法:与+左移1 a&b<<1
3.直到进位的为0为止
public class Solution {
public int Add(int num1,int num2) {
if(num1==0) return num2;
if(num2==0) return num1;
int result=0; int carry=0;
while(num2!=0){
result=num1^num2;
carry=(num1&num2)<<1;
num1=result;
num2=carry;
}
return result;}}
2. 二进制中1的个数
1)除2取模法
2)二进制移位法
直接将整数看成二进制,然后采用移位的方法。让一个数0x01
从右向左与val的每一位进行&操作来判断
//超时,所以不妨找到最右边的1
public int NumberOf1(int n) {
int val=1; int count=0;
while(n!=0){
if((val & n)!=0) count=count+1;
val=val<<1;
}
return count;
}}
3)2)的进阶,找到最右边的1
思路:n-1会使得最右边1变0,最右边1右边的0变1
再对其进行与运算,最右边1会变成0,能做多少次这种运算即证明有多少个1
public int NumberOf1(int n) {
int count=0;
while(n!=0){
n=n&(n-1);
count++;
}
return count;}
3.数值的整数次方
//不如用快速幂法
public double Power(double base, int exponent) {
if(exponent==0) return 1;
double a=p(base,exponent);
if(exponent>0) return a;
else return 1/a;
}
public double p(double base, int exponent) {
if(base==0) return 0;
if(exponent==0) return 1;
double result=1; exponent=Math.abs(exponent);//这里exponent一定要为绝对值
while(exponent!=0){
if(exponent%2==1) result=result*base;
base=base*base;
exponent=exponent/2;
}
return result;
}
4.数组中只出现一次的两个数字
一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
要求:空间复杂度 O(1),时间复杂度 O(n)
思路:位运算异或(^)
/*1.利用a^b^a=b来计算数组,最终留下c^d的值(cd只出现一次),^(异或)
2.找出cd不相等的位数:ca异或的话,相等为0,不等为1,那么用&1不断向左判断找不为0的数即可
3.根据这个不相等的位数可以把数组分成两组了
*/
import java.util.*;
public class Solution {
public int[] FindNumsAppearOnce (int[] array) {
int temp=0;
for(int mask:array){
temp=temp^mask;
}
int num=1;
while((num&temp)==0){
num=num<<1;
}
//开始把数组分成两组
int a=0; int b=0;
for(int mask:array){
if((mask&num)==0) a=a^mask;
else b=b^mask;
}
if(a>b){//位运算交换
a=a^b;
b=b^a;
a=a^b;
}
return new int[]{a,b};
}
}
5.求1+2+3+...+n
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
思路: 1.求和公式
2.循环求和
3.递归
4.短路求值(修改递归)
作为"&&"和"||"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假, 求值过程便告终止,这称之为短路求值。
假如expr1和expr2都是表达式,并且expr1的值为0,在下面这个逻辑表达式的求值过程中:
expr1 && expr2 expr2将不会进行求值,因为整个逻辑表达式的值已经可以确定为0。
expr1的值为1, expr1 || expr2 expr2将不会进行求值,因为整个逻辑表达式的值已经确定为1。
因此可以利用左边的表达式来作为递归结束的判断条件。因此递归的表达式就在右边了。而想到递归的解法,必然是sum=Sum(n)=Sum(n-1)+n
使用&&,结束条件在左边,只能是n=0时结束,即从n递减到0结束,
由于左边需要不断的进行条件判断,因为需要一个每次递归后都递减的变量,而n是递减的,因此用n来作为左边的变量,int sum = n;
而短路求值左边可以写为(n>0)或(n!=0),右边写为sum +=sum(n-1),再加一个判断(实际上需要保证右边的条件一直为真),因此java版的解法就出来了.
*/
public int Sum_Solution(int n) {
int sum=n;
boolean c=(n!=0)&&((sum+=Sum_Solution(n-1))>0);
return sum;
}