构建乘积数组
题目描述:
给定一个数组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];)
思路分析:
用两个数组分别存放0 ~ i-1 项的乘积和 i+1 ~ n-1项的乘积,最后把这两个数组对应项相乘即为数组B。
算法实现:
public class Solution {
public int[] multiply(int[] A) {
int[] f2 = new int[A.length];
int[] f3 = new int[A.length];
int ans1 = 1;
int ans2 = 1;
for(int i = 0 , j = A.length - 1; i < A.length ; i++ , j--){
f2[i] = ans1;
ans1 *= A[i];
f3[j] = ans2;
ans2 *= A[j];
}
int[] b = new int[A.length];
for(int k = 0; k < A.length; k ++){
b[k] = f2[k] * f3[k];
}
return b;
}
}
正则表达式匹配
题目描述:
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
思路分析:
-
当模式中的第二个字符不是“*”时:
- 1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。
- 2、如果 字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。
-
而当模式中的第二个字符是“*”时:
如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:- 1、模式后移2字符,相当于x*被忽略;
- 2、字符串后移1字符,模式后移2字符;
- 3、字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位;
算法实现:
public class Solution {
public boolean match(char[] str, char[] pattern) {
if (str == null || pattern == null) {
return false;
}
int strIndex = 0;
int patternIndex = 0;
return matchCore(str, strIndex, pattern, patternIndex);
}
public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) {
//有效性检验:str到尾,pattern到尾,匹配成功
if (strIndex == str.length && patternIndex == pattern.length) {
return true;
}
//pattern先到尾,匹配失败
if (strIndex != str.length && patternIndex == pattern.length) {
return false;
}
//模式第2个是*,且字符串第1个跟模式第1个匹配,分3种匹配模式;如不匹配,模式后移2位
if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') {
if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
return matchCore(str, strIndex, pattern, patternIndex + 2)//模式后移2,视为x*匹配0个字符
|| matchCore(str, strIndex + 1, pattern, patternIndex + 2)//视为模式匹配1个字符
|| matchCore(str, strIndex + 1, pattern, patternIndex);//*匹配1个,再匹配str中的下一个
} 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;
}
}
表示数值的字符串
题目描述:
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+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) {
String s = new String(str);
try{
Double.parseDouble(s);
}catch(Exception e){
return false;
}
return true;
}
}
利用正则表达式
[] : 字符集合
() : 分组
? : 重复 0 ~ 1 次
+ : 重复 1 ~ n 次
* : 重复 0 ~ n 次
. : 任意字符
\\. : 转义后的 .
\\d : 数字
public boolean isNumeric(char[] str) {
if (str == null || str.length == 0)
return false;
return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?");
}
字符流中第一个不重复的字符
题目描述:
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
思路分析:
用一个Map集合维护字符和字符出现次数之间的关系,定义一个StringBuilder用来保存字符流,每调用一次Insert方法,就追加到字符流中,并修改map中对用字符出现的次数,如果说map中对应字符只出现一次则返回次字符即可,否则返回‘#’。
算法实现:
public class Solution {
private Map<Character,Integer> map = new HashMap<>();
private StringBuilder str = new StringBuilder();
int index = 0;
//Insert one char from stringstream
public void Insert(char ch)
{
str.append(ch);
map.put(ch,map.getOrDefault(ch,0) + 1);
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
while(index < str.length()){
if(map.get(str.charAt(index)) == 1)
return str.charAt(index);
index ++;
}
return '#';
}
}
链表中环的入口结点
题目描述:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路分析:
设置快慢指针,都从链表头出发,快指针每次走两步,慢指针一次走一步,假如有环,一定相遇于环中某点。接着让两个指针分别从相遇点和链表头出发,两者都改为每次走一步,最终相遇于环入口。
算法实现:
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
ListNode fast = pHead;
ListNode slow = pHead;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow)
break;
}
if(fast == null || fast.next == null)
return null;
slow = pHead;
while(slow != fast){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}