位运算,异或,与运算
前言:当前内容只用来回忆复习,java编写,代码尽可能带注释,部分题目附上解题思路。如有错误,请指出,谢谢。
感悟:刷题重在思路以及巩固知识点,而不是刷题进度。
重点:位运算,异或实现无进位加法,与运算找出需要进位的位置
1、扑克牌顺子
题目描述
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
1.1 类似哈希数组的思想,数组下标作为键,数组内容作为值
public class Solution {
public boolean isContinuous(int [] numbers) {
// 数组中应该有5个数,表示5张牌,否则false
if(numbers == null || numbers.length != 5)
return false;
// 若没有大小王,就不能任意替代,那么剩下的数字必须是顺子,最大最小值差为4
// 若存在大小王,认为0,存在替代可能,那么,差值不能超过5,否则无法弥补中间缺的数字
// 结论:1、非0数字不能重复,2、非0个数的差值不能超过5,即小于5,
// 3、0的个数就是大小王的个数,<=4, 4、输入的数范围为0-13的整数
int[] arr = new int[14]; // 每一索引对应一个数字,存放的值就是出现次数
for(int i = 0; i < 5; i++){
int pos = numbers[i];
if(pos < 0 || pos >13)
return false; // 去除在0-13外的情况
arr[pos]++; // 存入出现次数
// 非0次数的判断,去重
if(pos > 0 && arr[pos] > 1)
return false; // 如果非0数字出现超过1次,那么肯定不是顺子
// 0数字,万能数字,次数的判断,<=4
if(pos == 0 && arr[pos] > 4)
return false; // 如果万能数字超过4次,那么肯定出错
}
// 非0数字至少有一个,因为最多4个王
// 非0数字1-13, 1个或超过1个,最大最小值的差必须小于5,
int min = 14;
int max = 0;
for(int pos = 1; pos <= 13; pos++){
if(arr[pos] != 0){
min = pos < min ? pos : min;
max = pos > max ? pos : max;
}
}
if((max-min) >= 5)
return false;
return true;
}
}
1.2 将数组排序
import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
// 数组中应该有5个数,表示5张牌,否则false
if(numbers == null || numbers.length != 5)
return false;
// 若没有大小王,就不能任意替代,那么剩下的数字必须是顺子,最大最小值差为4
// 若存在大小王,认为0,存在替代可能,那么,差值不能超过5,否则无法弥补中间缺的数字
// 结论:1、非0数字不能重复,2、非0个数的差值不能超过5,即小于5,
// 3、0的个数就是大小王的个数,<=4, 4、输入的数范围为0-13的整数
for(int i = 0; i < 5; i++){
int val = numbers[i];
if(val < 0 || val > 13)
return false;
}
Arrays.sort(numbers); // 排序后,最后一个肯定是非0数字的最大值,顺序遍历找到第一个不为0的数字即为非0最小值
int pos = 0;
while(numbers[pos] == 0){
pos++;
}
if(pos > 4)
return false; // 大小王总数超过4,说明错误
// 将所有非0的数遍历,如果有重复的数, 或是两数之差>=5,输出false
for(int j = pos; j<numbers.length-1; j++)
{
if(numbers[j] == numbers[j+1])
return false;
if(numbers[j+1]-numbers[pos]>=5)
return false;
}
return true;
}
}
2、孩子们的游戏
题目描述
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1
2.1
在这里插入代码片
3、求1+2+3+…+n
题目描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
3.1 与逻辑的短路特性可以作为递归结束条件
public class Solution {
public int Sum_Solution(int n) {
//n <= 0 是退出循环条件
// 这里n为负值返回自身
boolean flag = (n > 0) && ((n += Sum_Solution(n-1) ) > 0 );
return n;
}
}
4、不用加减乘除做加法
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
4.1 异或运算 配合 与运算 实现加法
public class Solution {
public int Add(int num1,int num2) {
// 不能用传统的四则运算实现加法,那就只有最底层的位运算了
// 异或实现的是无进位加法, 与运算可以找出进位
int sum = num1 ;
int add = num2 ;
while(add != 0){
int tmp = sum ^ add; // 保存无进位加法结果
add = (sum & add ) << 1; // 保存进位条件,若判断当前位置同为1,那么需要在当前位置的高一位进位
sum = tmp;
}
return sum;
}
}
5、把字符串转换成整数
题目描述
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
示例1
输入:
+2147483647
1a33
输出:
2147483647
0
5.1 主要关注点在整形溢出
public class Solution {
public int StrToInt(String str) {
// 排除空指针问题
if(str == null || str.length() == 0)
return 0;
// 只有在字符串头加上+-号,以及字符创中不能出现非数字字符才能转为数字
int flag = 1; // 默认是正数,因为负数,字符串头必须要加—号,正数可以加+或不加+
// 有可能出现数字溢出的情况
int sum = 0; // 设置初始值
for(int i = 0; i < str.length(); i++){
// 判断符号位
if(i ==0 && str.charAt(i) == '-'){
flag = -1;
continue;
}
if(i == 0 && str.charAt(i) == '+'){
continue;
}
if(str.charAt(i) < '0' || str.charAt(i) > '9')
return 0; // 存在非法字符直接返回
// 数字溢出情况, 数字溢出就是超出了边界,如果为正数,sum不能超过Int的最大值
// 若为负数,sum不能超过Int的最小值的绝对值
int tmp = sum;
int cur = str.charAt(i) - '0';
sum = (sum * 10 + cur);
if(flag == 1 && tmp >= Integer.MAX_VALUE/10 && cur >7){
return 0;
}
if(flag == -1 && tmp >= Integer.MAX_VALUE/10 && cur > 8 ){
return 0;
}
}
return flag * sum;
}
}
疑惑?
这题的结果,竟然能出现超过整数的最小值Integer.MIN_VALUE,如-2147483649情况,是不是哪里有问题?