剑指offer——其二
正则匹配
请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
采用递归的方式:
str的指针i和pattern的指针j:
有些比如str="",pattern=".*"|| str="",pattern=""等情况也需要考虑
如果同时扫描完 str和pattern,返回 true
如果扫描完pattern却没有扫描完str,返回false
如果j有下一个字符且下一个是*
如果str没有扫描完且pattern[j]==str[i]||pattern[j]=='.'
return match(str,pattern,i,j+2);匹配0次
match(str,pattern,i+1,j+2);匹配1次
match(str,pattern,i+1,j);匹配多次
否则 match(str,pattern,i,j+2);匹配不上返回0次
如果str没有扫描完且pattern[j]=='.'||str[i]==pattern[j]
return match(str,pattern,i+1,j+1);
return false;
public boolean match(char[] str,char[] pattern,int i,int j){
if(str.length==i&&pattern.length==j) return true;
if(str.length!=i&&pattern.length==j) return false;
if(j<pattern.length-1&&pattern[j+1]=='*'){
if(i!=str.length&&(str[i]==pattern[j]||pattern[j]=='.'))
return match(str,pattern,i+1,j)||match(str,pattern,i,j+2)||match(str,pattern,i+1,j+2);
else {
return match(str, pattern, i, j+2);}
}
if(str.length!=i&&(pattern[j]=='.'||str[i]==pattern[j])) return match(str, pattern, i+1, j+1);
return false;
}
判断字符串是否为数值
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
正则表达式,简单明了:
import java.util.regex.Pattern;
public class Solution {
public boolean isNumeric(char[] str) {
String pattern = "^[-,+]?\\d*(?:\\.\\d*)?(?:[e,E][+,-]?\\d+)?$";
String s = new String(str);
return Pattern.matches(pattern,s);
}
}
"[1]?\d(?:\.\d)?(?:[e,E][+,-]?\d+)?$";
^$正则表达的起始和截止
[-,+]?:+或-出现0次或1次
\d*数字出现多次
(?:.\d*)?:(小数点+数字可出现多次)这些东西出现0次或1次
另一个()同理
找出字符流中第一个只出现一次的字符.
当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。如果当前字符流没有存在出现一次的字符,返回#字符
采用字符哈希的方法,记录读入的字符,并设置一个队列,如果出现就入队.
获取时,判断队首元素的哈希数组是否为1.
import java.util.Queue;
import java.util.LinkedList;
import java.lang.Character;
public class Solution {
int[] charCnt=new int[128];
Queue<Character> queue=new LinkedList<Character>();
//Insert one char from stringstream
public void Insert(char ch)
{
charCnt[ch]++;
queue.add(ch);
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
Character CHAR=null;
char c=0;
while((CHAR=queue.peek())!=null){
c=CHAR.charValue();
if(charCnt[c]==1)
return c;
else queue.remove();
}
return '#';
}
}
判断一个链表是否有环
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:快慢指针,当两者相遇,从相遇点和起点一起走再次相遇就是环的起点。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
ListNode low=pHead,fast=pHead;
ListNode meet=null;
while(fast!=null){
low=low.next;
fast=fast.next;
if(fast!=null)
fast=fast.next;
if(fast==low)
{meet=fast;
break;}
}
if(meet==null) return null;
while(pHead!=null&&meet!=null){
if(pHead==meet)
return pHead;
pHead=pHead.next;
meet=meet.next;
}
return null;
}
}
删除链表中的重复节点
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode deleteDuplication(ListNode pHead)
{
if(pHead==null||pHead.next==null) return pHead;
ListNode head=new ListNode(0);
head.next=pHead;
ListNode p=head.next,q=head;
while(p!=null){
if(p.next!=null&&p.val==p.next.val){
while(p.next!=null&&p.val==p.next.val)
p=p.next;
q.next=p.next;
p=p.next;
}else{
q=q.next;
p=p.next;
}
}
return head.next;
}
}
这个代码比较好是因为它创建了头部节点。设两个指针p和q,以p为探索指针,向前寻找重复的最后一个节点,将q的下一个设为p的下一个节点,然后继续寻找,更新q的下一个节点,直到找到下一个没有重复的节点时再更新q的节点。
二叉树中序遍历问题
给定一个二叉树和其中一个节点,请找出中序遍历顺序的下一个节点并返回
思路:这里有几种情况,
如果该节点有右子树,那就是右子树或者右子树的最左节点
如果该节点没有右子树,该节点是其父节点的左子树,那么就是父节点
如果该节点没有右子树,该节点是其父节点的右子树,那么就是一直寻找到不是父节点右子树的那个父亲..
还要考虑特殊情况,比如本树最后一个节点结果为null.
/*
public class TreeLinkNode {
int val;
TreeLinkNode left = null;//左子树
TreeLinkNode right = null;//右子树
TreeLinkNode next = null;//父节点
TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
if(pNode==null) return null;
if(pNode.right!=null){//情况1
pNode=pNode.right;
while(pNode.left!=null)//寻找右子树的最左节点
pNode=pNode.left;
return pNode;}
if(pNode.right==null){
if(pNode.next!=null&&pNode==pNode.next.left) return pNode.next;//情况2
if(pNode.next==null) return null;//防止根节点的特殊情况
if(pNode==pNode.next.right){//情况3
while(pNode.next!=null&&pNode==pNode.next.right){
pNode=pNode.next;
}
if(pNode.next==null) return null;//特殊情况本树最后一个节点
return pNode.next;
}
}
return null;
}
}
-,+ ↩︎