剑指offer 46-50
46 孩子们的游戏(圆圈中最后剩下的数)
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1
java中直接使用一个list来模拟,并使用一个索引cur类指向删除的位置,当cur的值为list的size,就让cur到头位置。
import java.util.*;
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n<1||m<1){
return -1;
}
List<Integer> list = new ArrayList<>();
//构建list
for(int i = 0;i<n;i++){
list.add(i);
}
int cur = -1;
while(list.size()>1){
for(int i = 0;i<m;i++){
cur++;
if(cur == list.size()){
cur = 0;
}
}
list.remove(cur);
cur--;//cur--的原因,因为新的list中cur指向了下一个元素,为了保证移动m个准确性,所以cur向前移动一位。
}
return list.get(0);
}
}
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if (n <= 0 || m <= 0) {
return -1;
}
int ans = 0;
for (int i = 2; i <= n; i++) {
ans = (ans + m) % i;
}
return ans;
}
}
47求1+2 +3+...
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)
public class Solution {
public int Sum_Solution(int n) {
int sum=(int)Math.pow(n, 2)+n;
return sum>>1;
}
}
48不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
两个二进制的相加结果是用一个异或门实现的;
两个二进制的进位结果是用一个与门来实现的。
public class Solution {
public int Add(int num1,int num2) {
if(num2==0)return num1;
while(num2!=0){
int a=num1^num2;
int b=(num1&num2)<<1;
num1=a;
num2=b;
}
return num1;
}
}
8. 字符串转换整数 (atoi)
请你来实现一个 atoi
函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下:
- 如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
- 假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
- 该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0 。
提示:
- 本题中的空白字符只包括空格字符
' '
。 - 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: "42"
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
示例 4:
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
因此返回 INT_MIN (−2
31
) 。
class Solution {
public int myAtoi(String str) {
str=str.trim();
if(str.length()==0||(!Character.isDigit(str.charAt(0))&&str.charAt(0)!='+'&&str.charAt(0)!='-'))return 0;
long ans=0L;
int i=Character.isDigit(str.charAt(0))?0:1;
boolean neg=(str.charAt(0)=='-');
while(i<str.length()&&Character.isDigit(str.charAt(i))){
ans=ans*10+(str.charAt(i++)-'0');
if(!neg&&ans>Integer.MAX_VALUE){
ans=Integer.MAX_VALUE;
break;
}
if(neg&&ans>1L+Integer.MAX_VALUE){
ans=1L+Integer.MAX_VALUE;
break;
}
}
return neg?(int) -ans:(int) ans;
}
}
49字符串转化为整数
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
public int StrToInt(String str) {
//最优解
if(str == null || "".equals(str.trim()))return 0;
str = str.trim();
char[] arr = str.toCharArray();
int i = 0;
int flag = 1;
int res = 0;
if(arr[i] == '-'){
flag = -1;
}
if( arr[i] == '+' || arr[i] == '-'){
i++;
}
while(i<arr.length ){
//是数字
if(isNum(arr[i])){
int cur = arr[i] - '0';
if(flag == 1 && (res > Integer.MAX_VALUE/10 || res == Integer.MAX_VALUE/10 && cur >7)){
return 0;
}
if(flag == -1 && (res > Integer.MAX_VALUE/10 || res == Integer.MAX_VALUE/10 && cur >8)){
return 0;
}
res = res*10 +cur;
i++;
}else{
//不是数字
return 0;
}
}
return res*flag;
}
public static boolean isNum(char c){
return c>='0'&& c<='9';
}
50数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
int[] count=new int[length];
for(int i=0;i<length;i++){
count[numbers[i]]++;
}
for(int i=0;i<length;i++){
if(count[i]>1){
duplication[0]=i;
return true;
}
}
return false;
}
}
class Solution { public int myAtoi(String str) { str=str.trim(); if(str.length()==0||(!Character.isDigit(str.charAt(0))&&str.charAt(0)!='+'&&str.charAt(0)!='-'))return0; long ans=0L; int i=Character.isDigit(str.charAt(0))?0:1; boolean neg=(str.charAt(0)=='-'); while(i<str.length()&&Character.isDigit(str.charAt(i))){ ans=ans*10+(str.charAt(i++)-'0'); if(!neg&&ans>Integer.MAX_VALUE){ ans=Integer.MAX_VALUE; break; } if(neg&&ans>1L+Integer.MAX_VALUE){ ans=1L+Integer.MAX_VALUE; break; } } return neg?(int) -ans:(int) ans; } }
一流的解决方案{
公众诠释myAtoi(字符串str){
STR = str.trim();
如果(str.length()== 0 ||(Character.isDigit(str.charAt(0))&& str.charAt(0)= '+' && str.charAt(0)=!!! ' - '))的回报0;
长ANS = 0L;
INT I = Character.isDigit(str.charAt(0))?0:1;
布尔NEG =(str.charAt(0)== ' - ');
而(ⅰ<str.length()&& Character.isDigit(str.charAt(I))){
ANS = ANS * 10 +(str.charAt(I ++) - '0');
如果(!NEG && ANS> Integer.MAX_VALUE的){
ANS = Integer.MAX_VALUE的;
打破;
}
如果(NEG && ANS> 1L + Integer.MAX_VALUE的){
ANS = 1L + Integer.MAX_VALUE的;
打破;
}
}
返回NEG(INT)-ans:(INT)ANS;
}
}
公众诠释myAtoi(字符串str){
STR = str.trim();
如果(str.length()== 0 ||(Character.isDigit(str.charAt(0))&& str.charAt(0)= '+' && str.charAt(0)=!!! ' - '))的回报0;
长ANS = 0L;
INT I = Character.isDigit(str.charAt(0))?0:1;
布尔NEG =(str.charAt(0)== ' - ');
而(ⅰ<str.length()&& Character.isDigit(str.charAt(I))){
ANS = ANS * 10 +(str.charAt(I ++) - '0');
如果(!NEG && ANS> Integer.MAX_VALUE的){
ANS = Integer.MAX_VALUE的;
打破;
}
如果(NEG && ANS> 1L + Integer.MAX_VALUE的){
ANS = 1L + Integer.MAX_VALUE的;
打破;
}
}
返回NEG(INT)-ans:(INT)ANS;
}
}