剑指offer 算法java

1.将字符串转化为数字

char'0'对应48'A'对应65'a'对应97

(1)简单点就是调用javaapi

inta=Integer.parseInt(“123”);

这样得到a=123

(2)string分解成一个个的char.然后将char转化为int。个位不需要乘,十位乘以10,百分乘以100,以此类推。

<1>string分解为一个个的char.

c语言中:

Stringa=”123”;

charx=a[0];

java:

Stringa=”123”;

charx=a.charAt(0);

<2>char转化为int

我们知道char是使用的ASCII码。

标准ASCII码也叫基础ASCII码,使用7位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母数字09、标点符号,以及在美式英语中使用的特殊控制字符。

int result;
char codePoint=a.charAt(0);
  if ('0' <= codePoint && codePoint <= '9') {
                result = codePoint - '0';
            } else if ('a' <= codePoint && codePoint <= 'z') {
                result = 10 + (codePoint - 'a');
            } else if ('A' <= codePoint && codePoint <= 'Z') {
                result = 10 + (codePoint - 'A');

<3>简单的来写的话

String a="12345"; 
int num=0; 
int total=a.charAt(a.length()-1)-'0'; 
System.out.println(total); 
char x; 
for(int i=0;i

我们用到了指数,所以调用Math.pow方法。

<4>这么写其实有很多点没有考虑到

例如:

  • 字符串是否为空字符串

  • 字符串是否为null

  • 字符串是否只有一位为零

  • 字符串中有负号

  • 字符串中有非数字字符

  • 字符串的边界条件,比如Stringa=“9999999999999999999999999999”,要考虑到最大的正正数和最小的负整数以及溢出。

如果有负号Stringa=“-12345”

代码如下更改

String mString=“54321”
int state;
private static final int IS_PLUS=1;
private static final int IS_NEGATIVE=2;
private static final int IS_OVERFLOW=3;
private static final int ERROR=4;
...
public static void main(String[] args){
StateJudge(String target);//判断是哪种情况
switch(state){
	case  IS_PLUS:
	ransferPlus(mString);
	break;
	case IS_NEGATIVE:
	transferNegative(mString);
	break;
	case IS_OVERFLOW:
	isOverflow();
	break;
	case ERROR:
	isError();
	break;
	...
	default:
	break;

}
}
tranferPlus(String target){}
transferNegative(String target){}
isOverflow(){}
isError(){}
StateJudge(String target){}

2.将整形转化为字符串

(1)调用javaapi

Strings=String.valueOf(int a);其他类型也是可以的。

(2)

<1>int转化为一个个char,先除再求余

举个例子654321

获得1:654321%10

获得2:(654321/10)%10

获得3:(654321/100)%10

获得4:(654321/1000)%10

获得5:(654321/10000)%10

获得6:(654321/100000)%10

chara1=6+'0';

chara2=5+'0';

<2>char拼接成String

chara='a';

charb='b';

Strings=“”+a+b;

注意前面要加个空字符串,这样才是String类型。否则是int类型的计算。相当于是97+98

3.在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序,请完成一个函数,输入一个二维数组和一个整数,判断数组中是否含有该整数。


剑指offer 算法java_第1张图片

获得二维数组的行数和列数方法:

int row=array.length();

int col=array[0].length();

public class Matrix { 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
int[][] a={ 
					{1,2,8,9}, 
					{2,4,9,12}, 
					{4,7,10,13}, 
					{6,8,11,15} 
					}; 
boolean found=false; 
int target=16; 
int row=0; 
int col=3; 
while(col>=0&&row<=3) 
{if(a[row][col]==target) 
	{found=true; 
   break;} 
else if(a[row][col]>target) 
	col--; 
else{ 
	row++; 
} 

	} 
System.out.println(found); 

	} 

}

4.Strings = null; 拼接问题

Strings = null;

s+= "abc";

System.out.println(s);

答案是nullabc.

5.请实现一个函数,把字符串中的每个空格替换成”%20”。例如输入“Weare happy.”,则输出”We%20are%20happy.”

(1)调用api

String mString2=mString1.replace(“”,”%20”);

如果是替换字符的话还可以用

StringmString2=mString1.replace('','x');

分别对应两个方法:

publicString replace(CharSequence target, CharSequence replacement) {}

publicString replace(char oldChar, char newChar) { }

(2)自己实现代码

剑指offer 算法java_第2张图片

代码如下:

class StringTest { 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		String mString = "we are happy!Today is a good day! "; 
		int num = 0; 
		int startLength = mString.length(); 
		for (int i = 0; i < startLength; i++) { 
			if (mString.charAt(i) == ' ') { 
				num++; 
			} 
		} 
		int finishLength = startLength + 2 * num; //获取新的字符串长度
		int indexOfOriginal = startLength-1; 
		int indexOfNew = finishLength-1; 
		char[] aa = new char[finishLength]; //定义类型为char的数组
		while (indexOfNew>=0&&indexOfNew>=indexOfOriginal) { 
			if (mString.charAt(indexOfOriginal) != ' ') { 
				aa[indexOfNew--] = mString.charAt(indexOfOriginal); 
			} else { 
				aa[indexOfNew--] = '0'; 
				aa[indexOfNew--] = '2'; 
				aa[indexOfNew--] = '%'; 
			} 
			--indexOfOriginal; 
		} 
		String mNewString = String.valueOf(aa); //将char类型数组转化为String
		System.out.println(mString); 
		System.out.println(mNewString); 
	} 
}

6.已知有一个数列,f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n);其中n是大于0的整数,求f(10)的值。

recursion:递归

class Recursion {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(fn(10));
	}

	private static int fn(int i) {
		// TODO Auto-generated method stub
		if (i == 1) {
			return 1;
		} else if (i == 2) {
			return 4;
		} else {
			return 2 * fn(i - 1) + fn(i - 2);
		}
	}
}

7.实现一个排序算法,要求时间效率为O(n)

剑指offer 算法java_第3张图片

思路:首先员工年龄是有范围的。统计出每个年龄出现的次数。某年龄出现n次,就在数组里设置几次改年龄。相当于排序了。

注意要考虑到输入的异常情况并处理,比如年龄大于100,小于0的错误输入情况。

循环100×n,时间复杂度为O(n).

代码如下:

	public static void ageSort(int[] age) {
		int length = age.length;
		int[] sortedAge = new int[length];
		int[] timesOfAge;
		int maxAge = 99;
		timesOfAge = new int[maxAge + 1];
		for (int i = 0; i < timesOfAge.length; i++) {
			for (int j = 0; j < length; j++) {
				if (age[j] == i) {
					timesOfAge[i]++;
				}
			}
		}
		int index = 0;
		for (int i = 0; i < timesOfAge.length; i++) {
			for (int j = 0; j < timesOfAge[i]; j++) {
				sortedAge[index] = i;
				index++;
			}
		}
	}

8.java实现二分法

采用二分法查找时,数据需是有序不重复的。这里按升序来排序。

	public static int dichotomy(int[] array, int num) {
		int index=0;
		int start=0;
		int end=array.length-1;
		while (start<=end) {
			index=(start+end)/2;
			if (numarray[index]) {
				start=index+1;
			} 
			else {
				return index;
			}
		}
		return -1;
	}

总结详细揣摩whle(start<=end)这句循环。

如果num不在array里面,并且比最后一个数大。

startend的变化情况,循环倒数第二次肯定是start=end.(start不断变大),最后一次start+1变的大于end。退出循环,没找到。

如果num不在array里面,并且比第一个数小。

startend的变化情况,循环倒数第二次肯定是start=end.(end不断变小),最后一次end-1变的小于start。退出循环,没找到。

9.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转,输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如{3,4,5,1,2}{1,2,3,4,5}的一个旋转,该数组的最小值。

直观解法:遍历数组,求除最小值。事件复杂度O(n).不满足要求。

规律:

(1)可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后面子数组的元素。

(2)最小的元素刚好是这两个子数组的分界线。

所以采用二分查找法实现O(logn)的查找。

要考虑其它特殊情况:

如果把排序数组的前面的0个元素搬到最后。这样就不会满足第一个元素总是大于或者等于最后一个元素

比如有重复数字的情况。

代码:

	public static int findMinIndex(int[] array) {
		int index = 0;
		int middle=0;
		int start=0;
		int end=array.length-1;
		while(startarray[start]) {
				start=middle;
			}
			else if (array[middle]

最后一次查找后,endstart1.index就是end

剑指offer 算法java_第4张图片

总结来说的话:除了没有任何规律的数组可以考虑用遍历,其他的都不会考虑优先遍历。

10.java实现冒泡排序

冒泡排序排序的总次数:n(n-1)/2

时间复杂度为:O(n2)

步骤:原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,

这样一趟过去后,最大或最小的数字被交换到了最后一位,

然后再从头开始进行两两比较交换。第一趟比较n次,那么最后一位是最大()的数。下一趟就不用再比较它了。

time=n+(n-1)+(n-2)+(n-3)+...0=n2-n(n+1)/2=n(n-1)/2

代码如下:

public static void bubbleSort(int[] a) {
		int temp=0;
		for (int i = a.length-1; i >0; i--) {
			for (int j = 0; j a[j+1]) {
					temp=a[j];
					a[j]=a[j+1];
					a[j+1]=temp;
				}
			}
		}
	}

总结:好好揣摩

for(int i = a.length-1; i >0; i--) {

for(int j = 0; j

}

}

这两句。



11斐波那契数列Fibonaccisequence

又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>2,n∈N*)
递归写法:

	public static int  getResult2(int n) {
		if (n<2) {
			return 1;
		}
		else {
			return getResult2(n-1)+getResult2(n-2);
		}
	}

剑指offer 算法java_第5张图片

明显效率大于O(n)。网上有推导说是O(n32n)n的三次方乘以2n次方)

循环写法:

	public static int getResult(int n) {
		int myResult = 0;
		int[] result = { 1, 1 };
		int first = result[0];
		int second = result[1];
		if (n < 2) {
			myResult = result[n];
		}
		for (int i = 2; i <= n; i++) {
			myResult = first + second;
			first = second;
			second = myResult;
		}
		return myResult;
	}

效率为O(n),面试建议用循环的写法来写。

12.二进制中1的个数

剑指offer 算法java_第6张图片

方法一:右移输入数(对于负数会造成死循环,原因是负数的符号为1)

输入数为正,循环次数为输入数转化成二进制的位数

public static int numberOfOne(int num) {
		int count=0;
		while (num!=0) {
			if ((num&1)!=0) {
				count++;
			}
			num=num>>1;
		}
		return count;
	}

方法二:左移1

循环次数与int类型的储存位数有关,所以这里是32次。

	public static int numberOfOne(int num) {
		int count = 0;
		int one = 1;
		while (one != 0) {
			if ((num & one) !=0) {
				count++;
			}
			one = one << 1;
			System.out.println("one"+one);
		}
		return count;
	}

one2one4one8one16one32one64one128one256one512one1024one2048one4096one8192one16384one32768one65536one131072one262144one524288one1048576one2097152one4194304one8388608one16777216one33554432one67108864one134217728one268435456one536870912one1073741824one-2147483648one0

13.代码实现Math.pow(doublebase,int exponent).实际是Math.pow(doublebase,double exponet);

自以为简单的想法:

double pow(double base,int exponent){
	double result=1.0;
	for(int i=0;i<=exponent,i++){
		result*=base;
	}
	return result;
}

这样写没有考虑0,负数的情况

先说指数为负数:

负数取绝对值,然后求结果,最后将结果求倒数。(这里求倒数会引入一个问题,就是分母不可不0,要注意控制,也就是0去负次方的时候)

再说指数为0:

结果为1.如果同时base为0. 0的0次方在数学上是没有意义的,因此输出0或者1都是可以接受的,要跟面试官说清楚,表示已经考虑到这个边界值了。

错误处理方式有三种:

方法返回值,全局变量,异常。

比如求倒数时就可以try,catch一下。

有个问题,就是doublefloat类型是有误差的,所以在比较相等的时候,不要用==。而是定义一个equal方法,相差在0.0000001(误差随意)内就表示相等






你可能感兴趣的:(剑指offer 算法java)