数学与数字:Let's play with numbers! 作为一家领先的互联网公司,腾讯也会同别的厂一样经常问及一些数学或者和数字相关的题目。这里我们希望求职者不仅可以做好数学运算的准备,也要巩固一下位运算相关的知识。
(*)问题二十八:整数反转
问题描述:
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。输入: -123
输出: -321注意:假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31, 2^31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
解题思路一:
字符串反向添加。 步骤一:判断前面有没有+或者-;步骤二:将数字转为String,再转成StringBuilder;步骤三:新建StringBuilder,反向添加之前StringBuilder的每一位的数字;步骤四:使用Integer.ValueOf()进行处理,若出现Execption,则返回零。我的提交执行用时已经战胜 43.89 % 的 java 提交记录。这样的刷题毫无意义。
代码示例一:
//1.indexOf 检索字符串位置 (查找给定字符串在当前字符串的位置,返回第一个字母所在下标)
//2.substring(int start,int end)方法用于返回一个字符串的子字符串\
//3.trim去除字符串两边的空白
//4.charAt 用于给定位置上的字符
//5.valueOf()将基本类型转换为字符串
class Solution {
public int reverse(int x){
StringBuilder sb = new StringBuilder(String.valueOf(x));
int plus = 1, i = 0;
if (sb.charAt(0) == '-') {
plus = 0;
i++;
} else if (sb.charAt(0) == '+') {
i++;
}
StringBuilder sb_02 = new StringBuilder();
for (int j = sb.length() - 1; j >= i; j--) {
sb_02.append(sb.charAt(j));
}
if (plus == 1) {
try {
return Integer.valueOf(sb_02.toString());
} catch (Exception e) {
return 0;
}
} else {
try {
return -Integer.valueOf(sb_02.toString());
} catch (Exception e) {
return 0;
}
}
}
}
解题思路二:
使用弹栈压栈的思路。 考虑大于或小于边界的结束条件。我的提交执行用时已经战胜 90.93 % 的 java 提交记录。
代码示例二:
class Solution {
public int reverse(int x) {
int rev = 0;
while(x != 0){
//压栈
int pop = x % 10;
x = x / 10;
//正数溢出的条件,
if(rev > Integer.MAX_VALUE / 10 || (rev == Integer.MAX_VALUE / 10 && pop > Integer.MAX_VALUE % 10)){
rev = 0;
break;
}else if(rev < Integer.MIN_VALUE / 10 || (rev == Integer.MIN_VALUE / 10 && pop < Integer.MIN_VALUE % 10)){
rev = 0;
break;
}
//弹栈
rev = rev * 10 + pop;
}
return rev;
}
}
问题二十九:回文数
问题描述:
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。示例 1:输入: 121输出: true。
解题思路一:
堆栈Stack和队列LinkedList解决(实现了Queue)。 步骤一:负数肯定不行;步骤二:利用除法计算该整数每一位的值,并放进Stack和LinkedList中;步骤三:利用堆栈先进后出和队列先进先出的特性进行每一位的判断。循环结束条件是栈不为空(!stack.isEmpty())。我的提交执行用时已经战胜 56.09 % 的 java 提交记录。
代码示例一:
class Solution {
public boolean isPalindrome(int x) {
if(x<0) return false;
LinkedList<Integer> linkedlist = new LinkedList<>();
Stack<Integer> stack = new Stack<>();
int tmp = 0;
while(x!=0){
tmp = x%10;
x = x/10;
linkedlist.add(tmp);
stack.add(tmp);
}
while(!stack.isEmpty()){
if(stack.pop()!=linkedlist.remove()){
return false;
}
}
return true;
}
}
解题思路二:
计算前半部分和后半部分是否相等。 步骤一:处理负数、个位数和10的情况;步骤二:计算后半部分,循环结束条件是后半部分大于等于前半部分。步骤三:当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。我的提交执行用时已经战胜 95.17 % 的 java 提交记录。
代码示例二:
public static boolean isPalindrome(int x) {
// 特殊情况:
// 如上所述,当 x < 0 时,x 不是回文数。
// 同样地,处理10和个位数。
if(x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revertedNumber = 0;
while(x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
// 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
// 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
// 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
return x == revertedNumber || x == revertedNumber/10;
}
问题三十:只出现一次的数字
问题描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?示例 1:输入: [2,2,1]输出: 1。
解题思路一:
HashSet大法好。 如果已包含该元素,移除掉,否则添加,最后返回hashset.iterator().next()即可。注意如何遍历一个HashSet。使用基于泛型的Iterator遍历器,如果它有next域,直接遍历即可。Iterator<Integer> it = hashset.iterator(); while ( it.hasNext()) {int str = it.next(); },我的提交执行用时已经战胜 24.53 % 的 java 提交记录。很明显使用了额外的空间。
代码示例一:
class Solution {
public int singleNumber(int[] nums) {
HashSet<Integer> hashset = new HashSet<>();
for(int i =0;i<nums.length;i++){
if(hashset.contains(nums[i])){
hashset.remove(nums[i]);
}else{
hashset.add(nums[i]);
}
}
//如何遍历一个HashSet
//Iterator<Integer> it = hashset.iterator();
//while (it.hasNext()) {
// int str = it.next();
//}
return hashset.iterator().next();
}
}
解题思路二:
异或位运算。 题目给了那么多已知条件,为什么要.....这么不敏感?异或之后一样的数字都变为零了啊。只剩下唯一出现的那一个元素。我的提交执行用时已经战胜 99.77 % 的 java 提交记录。
代码示例二:
class Solution {
public int singleNumber(int[] nums) {
int result = 0;
for(int i = 0;i<nums.length;i++){
result ^= nums[i];
}
return result;
}
}
问题三十一:求众数
问题描述:
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于n/2的元素。你可以假设数组是非空的,并且给定的数组总是存在众数。输入: [3,2,3];输出: 3。
解题思路一:
HashTable大法好。 记住以下几个API:查看当前Table是否包含key:hashmap.containsKey;获取当前key值所对应的value:hashmap.get(nums[i]);给HashTable赋值: hashmap.put(nums[i], ++value)。我的提交执行用时已经战胜 26.08 % 的 java 提交记录。
代码示例一:
class Solution {
public int majorityElement(int[] nums) {
HashMap<Integer, Integer> hashmap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (!hashmap.containsKey(nums[i])) {
hashmap.put(nums[i], 1);
} else {
//更新hashtable当前的值。
int value = hashmap.get(nums[i]);
hashmap.put(nums[i], ++value);
}
}
//考虑总数为奇数或偶数的情况,必须大于等于一半。
for (int key : hashmap.keySet()){
int cmp = (nums.length%2==0)?nums.length/2:nums.length/2+1;
if(hashmap.get(key)>=cmp)
return key;
}
return 0;
}
}
解题思路二:
采用阵地攻守的思想。 第一个数字作为第一个士兵,守阵地;count = 1;遇到相同元素,count++;遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,是主元素。我的提交执行用时已经战胜 95.61 % 的 java 提交记录。 (解题思路远比代码实现更重要)
代码示例二:
class Solution {
public int majorityElement(int[] nums) {
if(nums.length == 0) return -1;
int count = 1;
int nownumber = nums[0];
for(int i = 1;i<nums.length;i++){
if(count==0){
nownumber = nums[i];
count++;
}else if(nums[i]!=nownumber){
count--;
}else if(nums[i] == nownumber){
count++;
}
}
return nownumber;
}
}
解题思路三:
代码示例三:
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
问题三十二:2的幂
问题描述:
给定一个整数,编写一个函数来判断它是否是 2 的幂次方。输入: 1输出: true解释: 2^0 = 1。
解题思路一:
除二取余法。 步骤一:考虑边界情况,当小于等于零时,返回false,当等于1时,返回true;步骤二:循环除二取余(先取余再除以2),若余数不等于零,返回false。步骤三:循环结束条件使除以2的结果为零,此时如果余数为零,返回true,否则返回false。我的提交执行用时已经战胜 72.20 % 的 java 提交记录2的幂。
代码示例一:
class Solution {
public boolean isPowerOfTwo(int n){
if(n<=0) return false;
if(n==1) return true;
int remainder = 0;
while(n/2!=0){
remainder=n%2;
if(remainder != 0) return false;
n/=2;
}
return remainder==0?true:false;
}
}
解题思路二:
按位相与法。 利用与操作,若一个数n是2的幂次方,则2进制表达式一定为某一位为1,其余为0。则n-1则会变成后面的数全部变成1,原来1的位置变成0。例:n=16的2进制(000010000),则n-1=15的二进制(00001111),则(n&n-1)=0。
代码示例二:
class Solution {
public boolean isPowerOfTwo(int n){
return n>0&&(n&(n-1))==0;
}
}