【剑指Offer中的数学题】
二进制中1的个数
题目描述
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。
示例1
输入
复制
10
返回值
复制
2
解题思路
public class Solution {
public int NumberOf1(int n) {
int count = 0;
while( n!= 0){
count++;
n = n&(n - 1);
}
return count;
}
}
数值的整数次方
题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0。不得使用库函数,同时不需要考虑大数问题,也不用考虑小数点后面0的位数。
示例1
输入
复制
2.00000,3
返回值
复制
8.00000
示例2
输入
复制
2.10000,3
返回值
复制
9.26100
示例3
输入
复制
2.00000,-2
返回值
复制
0.25000
说明
2的-2次方等于1/4=0.25
解题思路
public class Solution {
public double Power(double base, int exponent) {
if(exponent == 0){
return 1;
}else if(exponent == 1){
return base;
}else if(exponent > 1){
double sum = 1;
for(int i = 1;i <= exponent;i++){
sum = sum * base;
}
return sum;
}else{
double sum = 1;
for(int i = -1;i >= exponent;i--){
sum = sum * base;
}
return 1/sum;
}
}
}
整数中1出现的次数(从1到n整数中1出现的次数)
题目描述
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数
例如,1~13中包含1的数字有1、10、11、12、13因此共出现6次
示例1
输入
复制
13
返回值
复制
6
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
StringBuilder temp = new StringBuilder();
for (int i = 1;i <= n;i++){
temp.append(i);
//System.out.println(temp);//输出temp的值
}
int count = 0;
//System.out.println(temp.getClass().toString());//查看temp的数据类型
for (int i = 0;i < temp.length();i++){
if(temp.charAt(i) == '1')
count++;
}
return count;
}
}
丑数
题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
示例1
输入
复制
7
返回值
复制
8
public class JZ33 {
public static int ugly(int n){
if(n <= 0)return 0;
int p2 = 0,p3 = 0,p5 = 0;
int[] dp = new int[n];
dp[0] = 1;
for (int i = 1; i < n; i++) {
dp[i] = Math.min(dp[p2] * 2,Math.min(dp[p3] * 3,dp[p5] * 5));
if (dp[i] == dp[p2] * 2) p2++;
if (dp[i] == dp[p3] * 3) p3++;
if (dp[i] == dp[p5] * 5) p5++;
}
return dp[n - 1];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
}
}
孩子们的游戏(圆圈中最后剩下的数)
题目描述
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1
示例1
输入
复制
5,3
返回值
复制
3
约瑟夫环问题
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;
}
}
public class JZ46 {
public int LastRemaining_Solution_1(int n, int m) {
if (n <= 0 || m <= 0)
return -1;
return n == 1 ? 0 : (LastRemaining_Solution_1(n - 1,m) + m) % n;
}
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);
}
}
求1+2+3+…+n
题目描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例1
输入
复制
5
返回值
复制
15
public class JZ47 {
public int Sum_Solution(int n) {
//等差数列的和,n/2 + n方/2
int sum = (int)Math.pow(n,2) + n;
//右移一位除以2
return sum >> 1;
}
}
不用加减乘除做加法
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
示例1
输入
复制
1,2
返回值
复制
3
public class Solution {
public int Add(int num1,int num2) {
int result;
int ans;
do{
result = num1 ^ num2;
ans = (num1 & num2) << 1;
num1 = result;
num2 = ans;
}while(ans != 0);
return result;
}
}
把字符串转换成整数
题目描述
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
输入描述:
输入一个字符串,包括数字字母符号,可以为空
返回值描述:
如果是合法的数值表达则返回该数字,否则返回0
示例1
输入
复制
“+2147483647”
返回值
复制
2147483647
示例2
输入
复制
“1a33”
返回值
复制
0
public class JZ49 {
public int StrToInt(String str){
int res = 0;
int flag = 0; //用来标识是整数还是负数
for (int i = 0;i < str.length();i++){
if (str.charAt(i) >= '0' && str.charAt(i) <= '9'){
res = res * 10 + str.charAt(i) - '0';
}else if (str.charAt(i) == '+'){
if (i > 0 || flag != 0)
return 0;
flag = 1; //置为整数
}else if (str.charAt(i) == '-'){
if (i > 0 || flag != 0) //
return 0;
flag = -1; //置为负数
}else
return 0;
}
return flag >= 0 ? res : res * flag;
}
}
剪绳子
题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
返回值描述:
输出答案。
示例1
输入
复制
8
返回值
复制
18
public class JZ67 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
System.out.println(cutRope(n));
}
private static int cutRope(int target) {
int a = 0;
int c = 0;
int maxValue = 2;
if (target == 2){
return 1;
}
if (target == 3){
return 2;
}
if (target % 3 == 0){
maxValue = (int) Math.pow(3,target/3);
}else {
a = target - 2;
c = a % 3;
maxValue = maxValue * (int)Math.pow(3,a/3);
if ( 0 != c){
maxValue = maxValue * c;
}
}
return maxValue;
}
}