面试题11:旋转数组的最小数字
java二分查找(实现很重要)
1、什么是二分查找?
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
2、二分查找的优缺点是什么?
二分查找(折半查找)算法,是数据结构中一个典型的算法,它的查询速度是非常快的,比较次数少,平均性能好。但是其也有缺点,缺点就是二分查找必须有个前提就是数组是有序的,而且插入删除都比较困难。
3、二分查找的前提:
必须是一个有序的序列。
4、二分查找原理解析(java代码实现)
首先我们定义一个数组
int[] arr = {11, 22, 33, 44, 55, 66, 77};
二分查找是由两个变量:left索引和right索引控制查询范围,通过不断的折半范围来缩小查询区间实现查询数据。下面通过java语言来实现二分查找。
首先主方法内定义好数组arr,并且定义需要查询的值(这个值可以通过Scanner对象在控制台获取,为了演示我就直接赋值了),然后输出结果。
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55, 66, 77};
//定义需要查询的值
int select_value = 66;
int index= getIndex(arr,select_value);
System.out.println("查询值所对应的索引为:" + index);
}
接下来就是定义一个方法用来实现二分查找了,这里定义了一个有参有返回值的方法getIndex,里面传递了两个参数,一个为数组arr,另一个就是需要查询的值select_value。
public static int getIndex(int[] arr,int select_value) {
//初始化最小值的索引为0
int left = 0;
//初始化最大值的索引为arr.length-1
int right = arr.length - 1;
//首尾相加再除以2得出中间索引
int mid = (left + right) / 2;
while (left<=right) { //确保程序不会重复查询,不会越界
if (select_value > arr[mid]) {
//如果查询的值比中间值大,则往右边区域找,就把最小索引改为中间索引右移一位
left = mid + 1;
} else if (select_value < arr[mid]) {
//如果查询的值比中间值小,则往左边区域找,就把最大索引改为中间索引左移一位
right = mid - 1;
} else {
//剩余的情况就是查询到了结果,那么就直接返回索引。
return mid;
}
mid = (left + right) / 2;
}
//没有查询到,则返回-1
return -1;
}
java快速排序(实现很重要)
1、快速排序是一种比较高效的排序算法,采用“分而治之”的思想,通过多次比较和交换来实现排序,在一趟排序中把将要排序的数据分成两个独立的部分,对这两部分进行排序使得其中一部分所有数据比另一部分都要小,然后继续递归排序这两部分,最终实现所有数据有序。
其优点是效率高,时间复杂度平均为O(nlogn),顾名思义,快速排序是最快的排序算法,耗费的资源少,最佳情况下,空间复杂度为O(logn),每一次都平分数组的情况,代码较为简单。
空间复杂度:好情况就是O(logn),坏情况就是O(n);
2、快速排序图
3、Java 代码实现快速排序
public static void main(String[] args) {
int[] arry = {9,8,7,6,5,4,3,2,1};
quickSort(arry,0, arry.length-1);
System.out.println(Arrays.toString(arry));
}
public static void quickSort(int[] arry,int left,int right){
//运行判断,如果左边索引大于右边是不合法的,直接return结束次方法
if(left>right){
return;
}
//定义变量保存基准数
int base = arry[left];
//定义变量i,指向最左边
int i = left;
//定义j ,指向最右边
int j = right;
//当i和j不相遇的时候,再循环中进行检索
while(i!=j){
//先由j从右往左检索比基准数小的,如果检索到比基准数小的就停下。
while(arry[j]<=base && i<j){
j--; //j从右往左检索
}
//如果检索到比基准数大的或者相等的就停下
while(arry[i]>=base && i<j){
i++; //i从左往右检索
}
//代码走到这里i停下,j也停下,然后交换i和j位置的元素
int tem = arry[i];
arry[i] = arry[j];
arry[j] = tem;
}
//如果上面while条件不成立就会跳出这个循环,往下执行
//如果这个条件不成立就说明 i和j相遇了
//如果i和j相遇了,就交换基准数这个元素和相遇位置的元素
//把相遇元素的值赋给基准数这个位置的元素
arry[left] = arry[i];
//把基准数赋给相遇位置的元素
arry[i] = base;
//基准数在这里递归就为了左边的数比它小,右边的数比它大
//排序基准数的左边
quickSort(arry,left,i-1);
//排右边
quickSort(arry,j+1,right);
}
//将快速排序和堆排序结合
public static void quickSort(List<Integer> items){
//异常条件检测
if(items.size() > 1){
List<Integer> smaller = new ArrayList<>();
List<Integer> same = new ArrayList<>();
List<Integer> larger = new ArrayList<>();
Intger chosenItem = items.get(items.size() / 2);
for (Integer i : items){
if(i < chosenItem){
smaller.add(i);
} esle if(i > chosenItem){
large.add(i)
} else{
same.add(i);
}
}
sort(smaller);//Recursive(递归的) call!
sort(larger);//Recursive(递归的) call!
items.clear();
items.addAll(smaller);
items.addAll(same);
items.addAlll(larger);
}
}
public static void sort(int []ages){
int oldestAge=100;
int []timesOfAges=new int[oldestAge];
int len=ages.length;
for(int i=0;i<len;i++){
timesOfAges[ages[i]]++;;
}
//排序
int index=0;
for(int i=0;i<oldestAge;i++){
for(int j=0;j<timesOfAges[i];j++){
ages[index]=i;
index++;
}
}
}
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
int left = 0;
int right = array.length - 1;
int mid = left;
while(array[left] >= array[right]){
if(right - left == 1){
mid = right;
break;
}
mid = (left + right) / 2;
if(array[mid] >= array[left]){
left = mid;
} else if(array[mid] <= array[right]){
right = mid;
}
}
return array[mid];
}
}
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
int left = 0;
int right = array.length - 1;
int mid = left;
while(array[left] >= array[right]){
if(right - left == 1){
mid = right;
break;
}
mid = (left + right) / 2;
//如果下标为 left、right和mid指向的三个数字相等,则只能顺序查找
if(array[left] == array[right] && array[mid] == array[left]){
int result = array[left];
for(int i = left + 1; i <= right; i++){
if(result > array[i])
result = array[i];
}
return result;
}
if(array[mid] >= array[left]){
left = mid;
} else if(array[mid] <= array[right]){
right = mid;
}
}
return array[mid];
}
}
import java.util.*;
public class Solution {
public int minNumberInRotateArray(int [] array) {
//数组一定有元素
int res = array[0];
//遍历数组
for(int i = 1; i < array.length; i++)
//每次维护最小值
res = Math.min(res, array[i]);
return res;
}
}
面试题12:矩阵中的路径
回溯法
public boolean hasPath (char[][] matrix, String word) {
//字符串转化为字符串数组
char[] words = word.toCharArray();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
//从[i,j]这个坐标开始查找
if (dfs(matrix, words, i, j, 0))
return true;
}
}
return false;
}
boolean dfs(char[][] board, char[] word, int i, int j, int index) {
if (边界条件的判断) {
return;
}
一些逻辑处理
boolean res;
//往右
res = dfs(board, word, i + 1, j, index + 1)
//往左
res |= dfs(board, word, i - 1, j, index + 1)
//往下
res |= dfs(board, word, i, j + 1, index + 1)
//往上
res |= dfs(board, word, i, j - 1, index + 1)
//上面4个方向,只要有一个能查找到,就返回true;
return res;
}
最终的完整代码如下
public boolean hasPath(char[][] matrix, String word) {
char[] words = word.toCharArray();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
//从[i,j]这个坐标开始查找
if (dfs(matrix, words, i, j, 0))
return true;
}
}
return false;
}
boolean dfs(char[][] matrix, char[] word, int i, int j, int index) {
//边界的判断,如果越界直接返回false
//index表示的是查找到字符串word的第几个字符
//如果这个字符不等于matrix[i][j],说明验证这个坐标路径是走不通的,直接返回false
if (i >= matrix.length || i < 0 || j >= matrix[0].length || j < 0 || matrix[i][j] != word[index])
return false;
//如果word的每个字符都查找完了,直接返回true
if (index == word.length - 1)
return true;
//把当前坐标的值保存下来,为了在最后复原
char tmp = matrix[i][j];
//然后修改当前坐标的值
//保证不会从进来的方向回去
matrix[i][j] = '.';
//走递归,沿着当前坐标的上下左右4个方向查找
boolean res = dfs(matrix, word, i + 1, j, index + 1)
|| dfs(matrix, word, i - 1, j, index + 1)
|| dfs(matrix, word, i, j + 1, index + 1)
|| dfs(matrix, word, i, j - 1, index + 1);
//递归之后再把当前的坐标复原
matrix[i][j] = tmp;
return res;
}
时间复杂度:O(mn*k^3),m和n是矩阵的宽和高,最坏的情况下遍历矩阵的所有位置,k是字符串的长度,下面的dfs我们可以把它看做是一棵4叉树,除了第一次的时候可以往4个方向走,其他情况下只能往3个方向走(进来的那个方向回不去)
空间复杂度:O(K),k是字符串的长度
面试题13:机器人的运动范围
threshold,英语单词,名词,意思是“入口;门槛;开始;极限;临界值”。
public class Solution {
//记录遍历的四个方向
int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
//记录答案
int res = 0;
//计算一个数字的每个数之和
int cal(int n){
int sum = 0;
//连除法算出每一位
while(n != 0){
sum += (n % 10);
n /= 10;
}
return sum;
}
//深度优先搜索dfs
void dfs(int i, int j, int rows, int cols, int threshold, boolean[][] vis){
//boolean[][] vis 用来判断该格子是否已被访问过
//越界或者已经访问过
if(i < 0 || i >= rows || j < 0 || j >= cols || vis[i][j] == true)
return;
//行列和数字相加大于threshold,不可取
if(cal(i) + cal(j) > threshold)
return;
//满足要求,遍历的格子树+1
res += 1;
//标记经过的位置
vis[i][j] = true;
//上下左右四个方向搜索
//int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for(int k = 0; k < 4; k++)
dfs(i + dir[k][0], j + dir[k][1], rows, cols, threshold, vis);
}
public int movingCount(int threshold, int rows, int cols) {
//判断特殊情况
if(threshold <= 0)
return 1;
//标记某个格子没有被访问过
boolean[][] vis = new boolean[rows][cols];
dfs(0, 0, rows, cols, threshold, vis);
return res;
}
}
java求任意数字的位数之和
import java.util.Scanner;
/**
* 用JAVA求任意一个数的各个位数之和
* @author Administrator
*
*/
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入一个数字:");
int num = sc.nextInt();
int sum=0;
while(num!=0){
sum = sum + num%10;
num = num/10;
}
System.out.println("所给数字的各个位数之和为:"+sum);
}
}
import java.util.*;
public class Solution {
//记录遍历的四个方向
int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
//记录答案
int res = 0;
//计算一个数字的每个数之和
int cal(int n){
int sum = 0;
//连除法算出每一位
while(n != 0){
sum += (n % 10);
n /= 10;
}
return sum;
}
public int movingCount(int threshold, int rows, int cols) {
//判断特殊情况
if(threshold <= 0)
return 1;
//标记某个格子没有被访问过
boolean[][] vis = new boolean[rows][cols];
//记录答案
int res = 0;
Queue<ArrayList<Integer> > q = new LinkedList<ArrayList<Integer>>();
//起点先入队列
//Arrays.asList()方法是将数组转化成List,是Arrays类中提供的静态方法
q.offer(new ArrayList<Integer>(Arrays.asList(0, 0)));
vis[0][0] = true;
while(!q.isEmpty()){
//获取符合条件的一步格子
ArrayList<Integer> node = q.poll();
res += 1;
//遍历四个方向
for(int i = 0; i < 4; i++){
int x = node.get(0) + dir[i][0];
int y = node.get(1) + dir[i][1];
//符合条件的下一步才进入队列
if(x >= 0 && x < rows && y >= 0 && y < cols && vis[x][y] != true){
if(cal(x) + cal(y) <= threshold){
q.offer(new ArrayList<Integer>(Arrays.asList(x, y)));
vis[x][y] = true;
}
}
}
}
return res;
}
}
面试题14:剪绳子
public class Solution {
public int cutRope(int target) {
int[] arr = new int[target + 1];
arr[1] = 1;
for(int i = 2; i <= target; i++){
for(int j = 1; j < i; j++){
arr[i] = Math.max(arr[i],
Math.max(j, arr[j]) * (Math.max(i - j, arr[i - j])));
}
}
return arr[target];
}
}
public int cutRope(int target) {
if (target == 2 || target == 3)
return target - 1;
int res = 1;
while (target > 4) {
//如果target大于4,我们不停的让他减去3
target = target - 3;
//计算每段的乘积
res = res * 3;
}
return target * res;
}
public int cutRope(int target) {
if (target == 2 || target == 3)
return target - 1;
else if (target % 3 == 0) {
//如果target是3的倍数,绳子全部剪为3
return (int) Math.pow(3, target / 3);
} else if (target % 3 == 1) {
//如果target对3求余等于1,我们剪出一个长度为4的,其他长度都是3
return 4 * (int) Math.pow(3, (target - 4) / 3);
} else {
//如果target对3求余等于2,我们剪出一个长度为2的,其他长度都是3
return 2 * (int) Math.pow(3, target / 3);
}
}
书上的贪婪算法解法:
public class Solution {
public int cutRope(int target){
if(target < 2){
return 0;
}
if(target == 2){
return 1;
}
if(target == 3){
return 2;
}
//尽可能多地剪去长度为3的绳子段
int timesOf3 = target / 3;
//当绳子最后剩下的长度为4的时候,不能再剪去长度为3的绳子
//此时更好的方法是把绳子剪成长度为2的炼两段,因为 2*2 >3*1
if(target - timesOf3 * 3 == 1){
timesOf3 -= 1;
}
int timesOf2 = (target - timesOf3 * 3) / 2;
return((int)Math.pow(3, timesOf3)) * ((int)Math.pow(2, timesOf2));
}
}
面试题15:二进制中1的个数
位运算
位运算是指把数字用二进制表示之后,对每一位上0或者1的运算。
以上仅就逻辑变量只有一位的情况得到了逻辑“与”、“或”、“非”、“异或”运算的运算规则。当逻辑变量为多位时,可在两个逻辑变量对应位之间按上述规则进行运算。特别注意,所有的逻辑运算都是按位进行的,位与位之间没有任何联系,即不存在算术运算过程中的进位或借位关系。
public class Solution {
public int NumberOf1(int n) {
int count = 0;
while(n){
if(n & 1){
count++;
n = n >> 1;
}
}
return count;
}
}
0x80000000存储和表示问题
负数在内存中的存储形式
(1)十进制负数以补码存储于内存上
-8的在内存上存储形式: 1...1000
(2)十六进制负数以原码存储在内存上
int i = 0x80000001
// i=-1在内存上表示为 10...01
(3)0x80000000的表示值
0x80000000的值为 -2^31
1后面的31位表示序号位,0...0【类似于数组中的0号位】,表示负数中的最小的一位。由于int的最小值为-2^31,排在负数从小到大的第0位,所以int i = 0x80000000 为 -(2^31)+ 0 = -2^31
(4)十进制的补码也符合符号位+序号位的原则
以-1为例,其补码为 1..1
11...1序号位为第2^31 -1位
所以其值为 -2^31 + 2^31 -1 = -1 符合预期
(5)总结
符号位+序号位原则,序号位从0开始,序号位的值是多少就在最小值的基础上加上多少。好像也是 符合正数的情况~~~。
数值 = 该符号下最小值 + 序号位表示数
在上面的例子中,其中0x表示16进制,f在16进制中就表示十进制数15,这样0xffffff就表示一个16进制的数fffffff
public class Solution {
public int NumberOf1(int n) {
int res = 0;
//遍历32位
for(int i = 0; i < 32; i++){
//按位比较
if((n & (1 << i)) != 0)
res++;
}
return res;
}
}
public class Solution {
public int NumberOf1(int n) {
int res = 0;
//当n为0时停止比较
while(n != 0){
//比较一次去掉一个1
n &= n - 1;
res++;
}
return res;
}
}
n & (n - 1) == 0;
int a = (0b)m ^ (0b)n
public class Solution {
public int NumberOf1(int a) {
int res = 0;
//当n为0时停止比较
while(a != 0){
//比较一次去掉一个1
a &= a - 1;
res++;
}
return res;
}
}
面试题16:数值的整次方
public class Solution {
public double Power(double base, int exponent) {
double result = 1.0;
for(int i = 1; i <= exponent; i++){
result *= base;
}
return result;
}
}
public class Solution {
public double Power(double base, int exponent) {
//处理负数次方
if(exponent < 0){
base = 1 / base;
exponent = -exponent;
}
double res = 1.0;
//累乘
for(int i = 0; i < exponent; i++)
res *= base;
return res;
}
}
public class Solution {
//快速幂
private double Pow(double x, int y){
double res = 1;
while(y != 0){
//可以再往上乘一个
if((y & 1) != 0)
res *= x;
//叠加
x *= x;
//减少乘次数
//使用右移运算符代替了 除以2
y = y >> 1;
}
return res;
}
public double Power(double base, int exponent) {
//处理负数次方
if(exponent < 0){
base = 1 / base;
exponent = -exponent;
}
return Pow(base, exponent);
}
}
面试题17:打印从1到最大的n位数
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型 最大位数
* @return int整型一维数组
*/
public int[] printNumbers (int n) {
// write code here
int maxNum = 0;
for(int i = 0; i < n; i++){
maxNum = maxNum + (int)(9 * Math.pow(10,i));
}
System.out.println(maxNum);
int [] arr = new int[maxNum];
for(int j = 0; j < maxNum; j++){
arr[j] = j + 1;
}
return arr;
}
}
import java.util.*;
public class Solution {
public int[] printNumbers (int n) {
//找到该n+1位数的最小数字
int end = 1;
for(int i = 1; i <= n; i++)
end *= 10;
//从1遍历到n+1位数的最小数字输出
int[] res = new int[end - 1];
for(int i = 1; i < end; i++)
res[i - 1] = i;
return res;
}
}
package algorithm.graph;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
printNumbers(5);
}
public static void printNumbers (int n) {
// write code here
if (n <= 0){
return;
}
char[] number = new char[(int)Math.pow(10, n) - 1];
//Java填充字符数组
Arrays.fill(number, '0');
number[0] = '0';
for (int i = 0; i < number.length; i++) {
System.out.println(i + 1);
}
}
}
主要的思想是:把两个数存在String中了,然后将每个数字取出,放到数组,由最末位开始计算,算加法,判断是否进位,进位则前位+1,若超过长度,则copy到新的数组。
或者:两个使用 fiil 填满字符数组,两个字符数组长度之和就是结果
面试题18:删除链表的结点
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
public ListNode deleteNode (ListNode head, int val) {
//加入一个头节点
ListNode res = new ListNode(0);
res.next = head;
//前序节点
ListNode pre = res;
//当前节点
ListNode cur = head;
//遍历链表
while(cur != null){
//找到目标节点
if(cur.val == val){
//断开连接
pre.next = cur.next;
break;
}
pre = cur;
cur = cur.next;
}
//返回去掉头节点
return res.next;
}
}
public ListNode deleteNode(ListNode head, ListNode toDeleteNode) {
if(head == null) return null;
//虚构头结点
ListNode dummy = new ListNode(0);
dummy.next = head;
//删除的节点不是末尾节点
if(toDeleteNode.next != null) {
//后一个节点覆盖删除节点
toDeleteNode.val = toDeleteNode.next.val;
//节点指向后一个节点的下一个节点
toDeleteNode.next = toDeleteNode.next.next;
}
//删除的节点是末尾节点
else {
ListNode cur = head;
ListNode pre = dummy;
while(cur != null) {
if(cur == toDeleteNode) {
pre.next = cur.next;
}
pre = cur;
cur = cur.next;
}
}
return dummy.next ;
}
第一种解法
此类题目,肯定是可以采用递归来解决的,递归循环找到每个不重复的节点,重新组成一个有序链表即可,代码如下
public ListNode firstdeleteDuplication(ListNode<Integer> pHead) {
if(null == pHead || null == pHead.next){
return pHead;
}
if(pHead.val == pHead.next.val){
ListNode node = pHead.next;
//找到下一个phead不相同的第一个节点
while (node != null && node.val == pHead.val ){
node = node.next;
}
return firstdeleteDuplication(node);
}else {
pHead.next =firstdeleteDuplication(pHead.next);
return pHead;
}
}
第二个解法
在第一种解法中,我们采用了递归的方式,我们也可以采用非递归的方式,直接循环判断,代码如下
public ListNode secondDeleteDuplication(ListNode<Integer> pHead) {
if(null == pHead || null == pHead.next){
return pHead;
}
//定义一个虚拟头节点
if(pHead == null || pHead.next == null) return pHead;
ListNode temp = new ListNode(-1);
//虚拟头结点的下一个结点设为头结点
temp.next = pHead;
ListNode pre = temp;
while(pHead != null && pHead.next != null){
ListNode next = pHead.next;
if(pHead.val == next.val){
//循环找到重复数字的最后一个结点
while(next != null && pHead.val == next.val){
next = next.next;
}
pre.next = next;
pHead = next;
}else{
pre = pHead;
pHead = pHead.next;
}
}
return temp.next;
}
面试题19:正则表达式匹配
import java.util.*;
public class Solution {
public boolean match (String ss, String pp) {
// 技巧:往原字符头部插入空格,这样得到 char 数组是从 1 开始,而且可以使得 f[0][0] = true,可以将 true 这个结果滚动下去
int n = ss.length(), m = pp.length();
ss = " " + ss;
pp = " " + pp;
//两者都转化成字符串数组
char[] s = ss.toCharArray();
char[] p = pp.toCharArray();
boolean[][] f = new boolean[n + 1][m + 1];
// 技巧:往原字符头部插入空格,这样得到 char 数组是从 1 开始,而且可以使得 f[0][0] = true,可以将 true 这个结果滚动下去
f[0][0] = true;
// f(i,j) 代表考虑 s 中的 1~i 字符和 p 中的 1~j 字符 是否匹配
for (int i = 0; i <= n; i++) {
for (int j = 1; j <= m; j++) {
// 如果下一个字符是 '*',则代表当前字符不能被单独使用,跳过
if (j + 1 <= m && p[j + 1] == '*') continue;
// 对应了 p[j] 为普通字符和 '.' 的两种情况
if (i - 1 >= 0 && p[j] != '*') {
f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
}
// 对应了 p[j] 为 '*' 的情况
else if (p[j] == '*') {
f[i][j] = (j - 2 >= 0 && f[i][j - 2]) || (i - 1 >= 0 && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.'));
}
}
}
return f[n][m];
}
}
i从0开始循环考虑的是上面这种情况
面试题20:表示数值的字符串
import java.util.*;
public class Solution {
//遍历字符串的下标
private int index = 0;
//有符号判断
private boolean integer(String s){
if(index < s.length() && (s.charAt(index) == '-' || s.charAt(index) == '+'))
index++;
return unsigned_integer(s);
}
//无符号数判断
private boolean unsigned_integer(String s){
int temp = index;
while(index < s.length() && (s.charAt(index) >= '0' && s.charAt(index) <= '9'))
index++;
return index > temp;
}
public boolean isNumeric (String str) {
//先判断空串
if(str == null || str.length() == 0)
return false;
//去除前面的空格
while(index < str.length() && str.charAt(index) == ' ')
index++;
int n = str.length() - 1;
//去除字符串后面的空格
while(n >= 0 && str.charAt(n) == ' ')
n--;
//限制的长度比下标少1
n++;
//全是空格情况
if(n < index)
return false;
//判断前面的字符是否是有符号的整数
boolean flag = integer(str);
//如果有小数点
if(index < n && str.charAt(index) == '.'){
index++;
//小数点前后有无数字可选
flag = unsigned_integer(str) || flag;
}
//如果有e
if(index < n && (str.charAt(index) == 'e' || str.charAt(index) == 'E')){
index++;
//e后面必须全是整数
flag = flag && integer(str);
}
//是否字符串遍历结束
return flag && (index == n);
}
}
import java.util.regex.Pattern;
public class Solution {
public boolean isNumeric (String str) {
//正则表达式匹配
String pattern = "(\\s)*[+-]?((\\d+(\\.(\\d+)?)?)|(\\.\\d+))([Ee][+-]?\\d+)?(\\s)*";
//根据匹配值返回
return Pattern.matches(pattern, str);
}
}