剑指offer题解11
48 数组中重复的数
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
分析:想使用标记法,但是如果不使用额外空间,0不好处理,那么就是用交换好了,把数字放在该在的位置,如果发现该位置已经有了正确的数字,那么就找到了重复的数字
public class Solution {
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
// Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
// 这里要特别注意~返回任意重复的一个,赋值duplication[0]
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
public boolean duplicate(int numbers[],int length,int [] duplication) {
if(numbers==null){
return false;
}
for(int i=0;i<numbers.length;i++){
while(numbers[i]!=i&&numbers[i]!=numbers[numbers[i]]){
swap(numbers,i,numbers[i]);
}
if(numbers[i]==numbers[numbers[i]]&&i!=numbers[i]){
duplication[0]=numbers[i];
return true;
}
}
return false;
}
private void swap(int[] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}
49 构建乘积数组
题目描述
给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。
分析:第一想法就是计算说有的乘积,然后除以这个数,但是不能使用出发,因此可以先从左边计算(缺失右边),再从右边计算(补充右边)
import java.util.Arrays;
public class Solution {
public int[] multiply(int[] A) {
int[] res=new int[A.length];
Arrays.fill(res,1);
int sum=1;
for(int i=1;i<res.length;i++){
sum*=A[i-1];
res[i]=sum;
}
sum=1;
for(int i=res.length-2;i>=0;i--){
sum*=A[i+1];
res[i]*=sum;
}
return res;
}
}
50 正则表达式匹配
题目描述
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
分析:
考虑特殊情况,有一个为空,或者都为空,返回false
假如pattern中的下一个字符是,那么有四种情况:*
str当前的字符与当前pattern中的字符匹配:
- *表示为匹配的个数为0,patternIndex+=2,
- *表示匹配个数为1,patternIndex+=2,strIndex+=1
- *表示匹配个数为多个,strIndex+=1
str当前的字符与当前pattern中的字符不匹配:参照上述第一条
如果pattern下一个字符不是,那么只有一种情况*:匹配成功或者失败
public class Solution {
public boolean match(char[] str, char[] pattern) {
if(str==null||pattern==null){
return false;
}
int strIndex=0,patternIndex=0;
boolean res=myMatch(str,pattern,strIndex,patternIndex);
return res;
}
private boolean myMatch(char[] str, char[] pattern, int strIndex, int patternIndex) {
//同时结束
if(strIndex==str.length&&patternIndex==pattern.length){
return true;
}
//patternIndex先结束
if(patternIndex==pattern.length){
return false;
}
//下一位是*
if (patternIndex+1<pattern.length&&pattern[patternIndex+1]=='*'){
//1. *0
//2. *1
//3. *n
//此时可能str已经结束,而pattern还没有结束
if(strIndex!=str.length&&(str[strIndex]==pattern[patternIndex]||pattern[patternIndex]=='.')){
return myMatch(str,pattern,strIndex,patternIndex+2)
||myMatch(str,pattern,strIndex+1,patternIndex+2)
||myMatch(str,pattern,strIndex+1,patternIndex);
}else {
//不匹配,可以认为pattern匹配为0
return myMatch(str,pattern,strIndex,patternIndex+2);
}
}
//下一位不是*
if (strIndex!=str.length&&(pattern[patternIndex]=='.'||str[strIndex]==pattern[patternIndex])){
return myMatch(str,pattern,strIndex+1,patternIndex+1);
}
return false;
}
}
51 表示字符的字符串
题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。
分析:判断小数点,E,正负号是否合法即可
public class Solution {
public boolean isNumeric(char[] str) {
//防御
if(str==null||str.length==0){
return false;
}
boolean hasE=false,decimal=false,sign=false;
for(int i=0;i<str.length;i++){
//处理e
if(str[i]=='e'||str[i]=='E'){
//e后有数字
if(i==str.length-1){
return false;
}
//e只能出现一次
if(hasE){
return false;
}
hasE=true;
}
//处理sign
else if(str[i]=='+'||str[i]=='-'){
//第二次出现符号
if(sign&&str[i-1]!='e'&&str[i-1]!='E'){
return false;
}
//第一次出现符号
if(!sign && i>0 && str[i-1]!='e'&&str[i-1]!='E'){
return false;
}
}
//处理小数点
else if(str[i]=='.'){
//小数点不能出现在E后,也不能出现两次
if(hasE||decimal){
return false;
}
decimal=true;
}
//处理不合法字符
else if(str[i]<'0'||str[i]>'9'){
return false;
}
}
return true;
}
}