剑指Offer系列之题46~题50
46.扑克牌顺子
从扑克牌随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。
找出最大最小值,0的数量,判断最大最小值的差中的空缺数是否小于等于0的个数
1.快排:
快排超时,使用Arrays.sort(numbers);
public class Solution {
public boolean isContinuous(int [] numbers) {
//大、小王=任意数字 A=1 J=11 Q=12 K=13 可以认为大小王是0
//5张牌 可能是无序的
if(numbers.length<1)
return false;
int diff=0;//数字之间的空缺
int count=0;//大小王的数量
quickSort(numbers,0,numbers.length-1);
for(int i=0;i<numbers.length-1;++i){
if(numbers[i]==0){//大小王的数量
count++;
}else{
if(numbers[i+1]==numbers[i]){//两者相等则不连续
return false;
}//差-1即两数字间空缺数字的数量
diff+=numbers[i+1]-numbers[i]-1;
}
}
if(diff<=count)//若空缺数字的数量小于大小王的个数
return true;
return false;
}
//快速排序
public void quickSort(int a[],int low,int high){
if(low<high){
int index=partition(a,low,high);
quickSort(a,low,index-1);
quickSort(a,index+1,high);
}
}
public int partition(int a[],int low,int high){
int temp=a[low];
while(low<high){
while(low<high && a[high]>temp)
high--;
a[low]=a[high];
while(low<high && a[low]<temp)
low++;
a[high]=a[low];
}
a[low]=temp;
return low;
}
}
2.找出最大最小值,计算差值:
public class Solution {
public boolean isContinuous(int [] numbers) {
//大、小王=任意数字 A=1 J=11 Q=12 K=13 可以认为大小王是0
//5张牌 可能是无序的
if(numbers.length<1)
return false;
int count=0;//大小王的数量
int max=-1;
int min=14;
int a[]=new int[5];//存储已出现的数字
int j=0;
for(int i=0;i<numbers.length;++i){
if(numbers[i]==0){
count++;
}else{
//遍历查看该数字是否已出现过
for(int k=0;k<5;++k){
if(a[k]==numbers[i])//已出现则返回false
return false;
}
if(numbers[i]<min)
min=numbers[i];
if(numbers[i]>max)
max=numbers[i];
a[j]=numbers[i];
j++;
}
}
int diff=max-min-(numbers.length-count-1);
return diff<=count;
}
}
47.圆圈中最后剩下的数
0,1,…,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字。
约瑟夫环。找到规律然后递归/循环;利用循环链表
\[约瑟夫环的公式:
f(n,m)=
\begin{cases}
0, &n=1\\
[f(n-1,m)+m]\%n, &n>1
\end{cases}
\]
1.循环:
public class Solution {
public int LastRemaining_Solution(int n, int m) {
//约瑟夫环
if(n<=0 || m<=0)//错误输入
return -1;
int last=0;
for(int i=2;i<=n;++i){//公式
last=(last+m)%i;
}
return last;
}
}
2.递归:
public class Solution {
public int LastRemaining_Solution(int n, int m) {
//约瑟夫环
if(n<=0 || m<=0)//错误输入
return -1;
if(n==1)
return 0;
return (LastRemaining_Solution(n-1,m)+m)%n;
}
}
3.循环链表:
数组模拟环。考虑每个变量的作用,考虑环如何表达等因素。
public class Solution {
public int LastRemaining_Solution(int n, int m) {
//约瑟夫环
//错误输入
if(n<=0 || m<=0)
return -1;
int temp[]=new int[n];//辅助数组,存储元素
int i=-1,step=0,count=n;//i为索引,step为走的步数(m),count为剩余的数量
while(count>0){
i++;
if(i>=n)//模拟环,当到达末尾时,从头开始
i=0;
if(temp[i]==-1)//若为-1,证明已删除
continue;
step++;
if(step==m){//走了m步,删除该元素(置-1),总数减一,步数重置为0
temp[i]=-1;
step=0;
count--;
}
}
return i;//返回跳出循环时i的值,即最后一个数字的索引
}
}
48.求1+2+3…+n
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A ? B:C)。
当这些操作不可用时,可以考虑
短路
操作当作递归退出条件。
短路+递归:
&&
和||
都可以
public class Solution {
public int Sum_Solution(int n) {
//利用短路操作 &&
int sum=n;
boolean flag=(n>0)&& ((sum+=Sum_Solution(n-1))>0);//若n小于等于0则不进行后面的操作
return sum;
}
}
49.不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
利用位运算。其中
异或
得到没有进位时的和,与
得到都为1的位,与左移一位
得到进位,最后相加(直到没有进位时)得到和。
1.位运算:
public class Solution {
public int Add(int num1,int num2) {
//三步走 先得到不进位的结果,然后得到进位,最后相加
if(num1==num2)//相等则左移一位 即*2
return num1<<1;
while(num2!=0){//若仍存在进位,继续进行运算
int p1=num1^num2;//step 1 异或运算得到没有进位时的和
int p2=(num1&num2)<<1;//step 2 与运算找到都为1的位,然后左移一位得到进位
num1=p1;
num2=p2;
}
return num1;
}
}
50.把字符串转换成整数
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
输入描述
:输入一个字符串,包括数字字母符号,可以为空
输出描述
:如果是合法的数值表达则返回该数字,否则返回0
遍历,依次相加组成结果。中间需要注意越界,符号等因素
1.遍历:
public class Solution {
public int StrToInt(String str) {
if(str==null || str.equals("")||str.equals(" "))//异常输入
return 0;
str=str.trim();//去首尾空格
boolean flag=true;//正负标志
if(str.charAt(0)=='-'){
flag=false;
str=str.substring(1,str.length());
}else if(str.charAt(0)=='+'){
str=str.substring(1,str.length());
}
long res=0;//long表达,防止越界
for(int i=0;i<str.length();++i){
char c=str.charAt(i);
if(c<48 || c>57)//若不是纯数字
return 0;
res+=(c-'0')*Math.pow(10,str.length()-i-1);//转化为整型
}
if(!flag){//添加符号
res= -res;
}
if(res>Integer.MAX_VALUE || res<Integer.MIN_VALUE)//判断是否越界
return 0;
return (int)res;
}
}
如有错误,欢迎指正