JZ50 数组中重复的数字
(简单)
题目
描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任一一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1
示例
输入:
[2,3,1,0,2,5,3]
返回值:
2
说明:
2或3都是对的
思路
用哈希法或者暴力解法都可以通过(因过于简单,不再赘述),但是没有用到条件:“所有数字都在0到n-1的范围内”,因此,很可能还有更巧妙的方法。
实现
暴力解法
public class Solution {
public int duplicate (int[] numbers) {
if (numbers.length == 0) {
return -1;
}
for (int i = 0; i < numbers.length - 1; i++) {
for (int j = i + 1; j < numbers.length; j++) {
if (numbers[i] == numbers[j]) {
return numbers[i];
}
}
}
return -1;
}
}
哈希解法
public class Solution {
public int duplicate (int[] numbers) {
HashSet<Integer> set = new HashSet<Integer>();
for(int i=0; i<=numbers.length-1; ++i){
if(set.contains(numbers[i]))return numbers[i];
else set.add(numbers[i]);
//利用set的STL性质(add时有重复返回false)可以优化效率,将上面两句替换为:
//if(!set.add(numbers[i]))return numbers[i];
}
return -1;
}
}
JZ48 不用加减乘除做加法
(简单)
题目
描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
示例
输入:
1,2
返回值:
3
思路
因为我这学期刚学完计算机组成原理,一看到这题,不用 +、-、*、/ 来计算两数之和,接着就想到了位运算,而 Java 中的位运算有:与(&)、或(|)、异或(^)、非(~),而此题只需要前三个即可。
两数相加的底层二进制实现,无非就是补码的运算,而此题并不是让考察原码和补码直接的转换,而考察的是对于位运算的熟悉程度和变通能力。
因为本题用位运算解决,因此为了方便起见,我们将加数和被加数都叫做两个二进制操作数。两个二进制操作数相加的结果,就是他们的未进位时的结果,加上进位数,而未进位时的结果可通过两数异或运算求得,进位数可通过两数与运算求得,因此,用一个 5 + 1 = 6 的例子来描述,则如下图所示:
实现
public class Solution {
public int Add(int num1,int num2) {
while (num2 != 0) {
int x = (num1 & num2) << 1; //进位:求与,并左移
num1 ^= num2; //未进位时的和:异或
num2 = x;
}
return num1;
}
}