数值的整数次方
题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
分析
这种题有一种很直观的求解方法,累乘,时间复杂度为O(n)。
使用递归求解,时间复杂度只有O(logn)。可以利用下面的公式来求解
a
a
a的
n
n
n次方:
a
n
=
{
a
n
/
2
×
a
n
/
2
,
if
n
为偶数
a
(
n
−
1
)
/
2
×
a
(
n
−
1
)
/
2
×
a
,
if
n
为奇数
,
a^n= \begin{cases} a^{n/2}\times a^{n/2}, &\text{if $n$为偶数}\\ a^{(n-1)/2}\times a^{(n-1)/2}\times a, &\text{if $n$为奇数}, \end{cases}
an={an/2×an/2,a(n−1)/2×a(n−1)/2×a,if n为偶数if n为奇数,
求解的时候要考虑周全,
- 当指数为0时,不管底数是多少,都得1;
- 当指数为1时,不管底数为多少,结果等于底数;
- 当底数为0时,如果指数为正数,结果为0;
- 当底数为0时,如果指数为非正数,则抛出异常;
- 当指数为正数的时候,考虑奇偶两种情况,按上面的公式计算;
- 当指数为负数的时候,即 a − n a^{-n} a−n,即计算 ( a n ) − 1 = 1 / a n (a^n)^{-1}=1/a^n (an)−1=1/an。
Java代码
public class Solution {
public double Power(double base, int exponent) {
// 指数特殊情况
if(exponent == 0)
return 1;
if(exponent == 1)
return base;
// 底数为0的情况
if(base == 0 && exponent > 0)
return 0;
if(base == 0 && exponent <= 0)
throw new RuntimeException();
// 指数为负数和正数的情况要分开考虑
int exp = exponent>0 ? exponent : -exponent;
double res = Power(base, exp>>1);
res *= res;
if((exp & 1) == 1)
res *= base;
if(exponent < 0)
res = 1 / res;
return res;
}
}
打印1到最大的n位数
题目描述
输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3一致到最大的3位数999。
分析
这道题看似简单,首先找到n位的最大的十进制数,例如n=5,最大的数字就是99999。然后利用循环从1开始打印出来。
但是要意识到这是一个大数问题。若这个n很大的时候,大到不管用int还是long都会溢出,就不能使用循环打印的方式求解。
使用字符串模拟数字,加上递归的方法,将问题转换成数字排列的解法。举例说明解法:
若n=3,可以先定义一个长度为4的字符串number[],
- number[0]存放的是百位数;
- number[1]存放的十位数;
- number[2]存放的是个位数;
- number[3]存放的是换行符’\n’。
先将百位数设为0,即number[0]=0,再令十位数为0,即number[1]=0,然后分别令个位(number[2])设为0,1,2,3,4,5,6,7,8,9,即可得到:
000 / 001 / 002 / …… / 008 / 009
循环结束后,再设置十位(number[1]=1),同理可得到:
010 / 011 / 012 / …… / 018 / 019
待得到 090 / 091 / 092 / …… / 098 / 099 的时候,再设置百位(number[0])为1。循环往复。最终即可打印出1 ~ 3位最大值999
其次,字符串输出为数字的形式,要注意高位为0不能输出,例如:001,如果直接输出不符合我们常规的做法,应该输出为1,即高位的0不输出,从不为0的最高位开始输出。还要注意不要把0打印出来。
Java代码
import java.util.*;
import java.util.regex.*;
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
Print1toMaxOfNDigits(n);
}
sc.close();
}
public static void Print1toMaxOfNDigits(int n) {
if(n<=0) // n一定是正整数
return;
// 字符数组number用来存放数值的各位数字
char[] number = new char[n];
// 每一位数字都是从0-9的循环
for(int i=0; i<10; i++) {
number[0] = (char)(i+48);
// 最高位number[0]固定之后,处理后面的低位数字
Print1ToMaxOfNDigitsRecursively(number, n, 0);
}
}
public static void Print1ToMaxOfNDigitsRecursively(char[] number, int length, int idx) {
// 如果已经处理到最后一位,则利用PrintNumber将字符数组以数字的格式输出
if(idx == length-1) {
PrintNumber(number);
return;
}
// 递归处理每一位,从0-9
for(int i=0; i<10; i++) {
number[idx+1] = (char)(i+48);
Print1ToMaxOfNDigitsRecursively(number, length, idx+1);
}
}
public static void PrintNumber(char[] number) {
int i=0;
while(i<number.length && number[i]=='0')
i++;
for(; i<number.length; i++)
System.out.print(number[i]);
System.out.println();
}
}
调整数组顺序时奇数位于偶数前面
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
分析
因为要保证相对位置不变,所以要采用类似于稳定排序的方法
方法1
冒泡法
从前向后遍历,每次发现两个相邻的数满足“前面一个是偶数,后面一个奇数”的条件,就两两进行交换。遍历
n
n
n次后可保证最后
n
n
n个数字是偶数。由于之后奇数和偶数之间进行了交换,奇数和奇数或者偶数和偶数之间没有交换,所以其相对位置保持不变。
方法2
选择排序法
从第1
(
i
=
1
)
(i=1)
(i=1)个元素开始判断,如果array[
i
i
i]是偶数,则向后找到第一个奇数,假设是array[
j
j
j]。则将array[
j
j
j]取出,将
i
i
i ~
(
j
−
1
)
(j-1)
(j−1)的元素依次向后移一位,然后将array[j]放到下标为
i
i
i的位置。
方法3
用空间换时间
新建一个数组保存奇数,然后将原数组中偶数依次排在后面(代码不展示)
Java代码
方法1
public class Solution {
public void reOrderArray(int [] array) {
for(int i=0; i<array.length; i++) {
for(int j=0; j<array.length-1-i; j++) {
if((array[j]&1)==0 && (array[j+1]&1)==1) {
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
}
方法2
public class Solution {
public void reOrderArray(int [] array) {
for(int i=0; i<array.length; i++){
if((array[i]&1)==1)
continue;
for(int j=i+1; j<array.length; j++){
if((array[j]&1)==0)
continue;
else{
int temp = array[i];
array[i] = array[j];
for(int k=j; k>i+1; k--){
array[k] = array[k-1];
}
array[i+1] = temp;
break;
}
}
}
}
}