第48题
题目描述: 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
思路分析:
1.字符串的首位可能有符号,首先需要判断是否有符号,并且记录符号的类型;
2.根据是否存在符号位来标记字符串的起始位;
3.依次将每个字符转为数字(取出字符和0作减法),拼接到结果中;
代码如下:
public class Solution {
public int StrToInt(String str) {
if(str.length() == 0)
return 0;
int flag = 0;
//第一个符号是+
if(str.charAt(0) == '+')
flag = 1;
//第一个符号是-
else if(str.charAt(0) == '-')
flag = 2;
//有符号则第二个数开始,没有则默认正数
int start = flag > 0 ? 1 : 0;
//用long类型存储最终值
long res = 0;
while(start < str.length()){
//如果有一位不是数字,直接返回0
if(str.charAt(start) > '9' || str.charAt(start) < '0')
return 0;
//拼接数字,通过字符和0作减法将字符转为数字
res = res * 10 + (str.charAt(start) - '0');
start ++;
}
return flag == 2 ? -(int)res : (int)res;
}
}
第49题
题目描述: 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路分析: 因为数字的范围是0到n-1,n为数组的长度。所以我们可以定义一个长度为n的数组用于记录对应数字出现的次数,数组的下标就是对应的数字,对应下标下的数组值就是数组出现的次数。
代码如下:
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
if(length==0||numbers==null){
return false;
}
//用于记录每个数出现的次数
int[] array = new int[length];
//记录每个数出现的次数,数组的下标就是对应的数,对应位置数组的值就是数出现的次数
for(int i=0;i<length;i++){
array[numbers[i]]++;
}
for(int i=0;i<length;i++){
if(array[i]>1){
duplication[0] = i;
return true;
}
}
return false;
}
}
第50题
题目描述: 给定一个数组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]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * … * A[n-1],B[n-1] = A[0] * A[1] * … * A[n-2];)
思路分析: 简单来说,就是B[i]的值为A数组中除了A[i]以外其余位置的值相乘,但是不能使用除法。下面借鉴了一下剑指offer的思路,主要是自己要分析清楚数组下标的关系。
代码如下:
public class Solution {
public int[] multiply(int[] A) {
int length = A.length;
int[] B = new int[length];
if(length!=0){
B[0] = 1;
//上半部分
for(int i =1;i<length;i++){
B[i] = A[i-1]*B[i-1];
}
//下半部分
int temp = 1;
for(int j = length-2;j>=0;j--){
temp = temp*A[j+1];
B[j] = B[j]*temp;
}
}
return B;
}
}
第51题
题目描述: 请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配。
思路分析: 分为两种情况:当前模式串的后一位是星号()和不是星号;
是星号: 1.模式串当前位置的值能和Str匹配上,如::abb与abb、.bb和abb;
2.模式串当前位置的值能和Str匹配不上,如:abbb 与bbb;
不是星号:那么判断模式串当前位置的值是不是和Str当前位置值相等;
此题使用两个索引分别指向模式串和字符串Str的当前比较位置。
代码如下:
public class Solution {
public boolean match(char[] str, char[] pattern)
{
//参数1代表需要匹配的字符串
//参数2是正则表达式
if(str == null || pattern == null){
return false;
}
int strIndex = 0;
int patternIndex = 0;
return matchCore(str,0,pattern,0);
}
public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex){
//1.strIndex到尾且patternIndex到尾
if(strIndex == str.length && patternIndex == pattern.length){
return true;
}
//2.strIndex没到尾且patternIndex到尾
if(strIndex != str.length && patternIndex == pattern.length){
return false;
}
//模式第2个是*
if(patternIndex + 1 < pattern.length && pattern[patternIndex+1] == '*'){
//1.字符串第1个跟模式第1个匹配(可能是字符 也可能是通配符)
if((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (strIndex != str.length && pattern[patternIndex] == '.')){
return matchCore(str,strIndex+1,pattern,patternIndex)
|| matchCore(str,strIndex,pattern,patternIndex+2)
|| matchCore(str,strIndex+1,pattern,patternIndex+1);
}else{
return matchCore(str,strIndex,pattern,patternIndex+2);
}
}
//模式第2个不是*,但是字符串第1个跟模式第1个匹配(相同或者是通配符),则都后移1位,否则直接返回false
if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
return matchCore(str, strIndex + 1, pattern, patternIndex + 1);
}
return false;
}
}
第52题
题目描述: 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。
代码如下:
public class Solution {
public boolean isNumeric(char[] str) {
if (str == null || str.length == 0)
return false;
return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?");
}
}
第53题
题目描述: 请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
思路分析: 涉及到字符出现的次数时,我们一般需要容器来保存它出现的次数。
代码如下:
import java.util.*;
public class Solution {
//存储次数
HashMap<Character,Integer> map = new HashMap<>();
//存储顺序
ArrayList<Character> list = new ArrayList<>();
//Insert one char from stringstream
public void Insert(char ch)
{
if(map.containsKey(ch)){
map.put(ch,map.get(ch)+1);
}else{
map.put(ch,1);
}
//添加到链表中
list.add(ch);
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
char ch = '#';
for(char c:list){
if(map.get(c)==1){
ch = c;
//找到第一个就返回
break;
}
}
return ch;
}
}