剑指offer 51~60
给定一个数组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.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int re[] = {0};
if (A.length == 0 || A == null) return re;
int len = A.length;
int B[] = new int[len];
int cnta = 1, cntb = 1;
for (int i = 0; i < len; i++) {
for (int j = 0; j < len - 1; j++) {
if (j < i) cnta *= A[j];
else cntb *= A[j + 1];
}
B[i] = cnta * cntb;
cnta = 1;
cntb = 1;
}
return B;
}
}
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
public class Solution {
public boolean match(char[] str, char[] pattern)
{
if (str == null || pattern == null) return false;
return matchCore(str, 0, pattern, 0);
}
public boolean matchCore(char[] str, int s, char[] pattern, int p) {
if (str.length <= s && pattern.length <= p) return true; //都匹配完了
if (str.length > s && pattern.length <= p) return false; //模式完了,字符串还有
if (p + 1 < pattern.length && pattern[p + 1] == '*') {
//当前pattern的下一个是*号
//字符串完了
if (s >= str.length) return matchCore(str, s, pattern, p + 2);
else {
if (pattern[p] == str[s] || pattern[p] == '.') {
//当前位置匹配完成,移动到下一个串
return matchCore(str, s, pattern, p + 2)
|| matchCore(str, s + 1, pattern, p + 2)
|| matchCore(str, s + 1, pattern, p);
} else return matchCore(str, s, pattern, p + 2);
}
}
//当前pattern不是*的时候
if (s >= str.length) return false;
else {
if (str[s] == pattern[p] || pattern[p] == '.') return matchCore(str, s + 1, pattern, p + 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) {
// 如果这个数使用科学计数法表示,将数字分成两部分判断
int posE = -1;
if (contains(str, 'E') || contains(str, 'e')) {
for (int i = 0; i < str.length; i++) {
if (str[i] == 'E' || str[i] == 'e') {
posE = i;
break;
}
}
//如果 'E' || 'e'在开始与结尾的位置,说明错误
if (posE == 0 || posE == str.length - 1) return false;
char left[] = new char[posE];
char right[] = new char[str.length - posE - 1];
left = subString(str, 0, posE);
right = subString(str, posE + 1, str.length);
// left判断与非科学计数法一样
// right判断必须为整数
if (startWith(right, '+') || startWith(right, '-')) {
right = subString(right,1, right.length);
}
return isDecimal(left) && isDigit(right);
} else return isDecimal(str);
}
static boolean isDigit(char[] num) {
for (int i = 0; i < num.length; i++) {
if (num[i] > '9' || num[i] < '0') return false;
}
return true;
}
static boolean contains(char[] str, char ch) {
for (int i = 0; i < str.length; i++) {
if (str[i] == ch) return true;
}
return false;
}
static boolean startWith(char[] str, char ch) {
if (str[0] == ch) return true;
return false;
}
static boolean isDecimal(char[] str) {
if (startWith(str, '-') || startWith(str, '+')) {
str = subString(str,1,str.length);
}
if (contains(str, '.')) {
int posE = -1;
for (int i = 0; i < str.length; i++) {
if (str[i] == '.') {
posE = i;
break;
}
}
if (posE == 0 || posE == str.length - 1) return true;
char[] left = new char[posE];
char[] right = new char[str.length - posE - 1];
left = subString(str,0, posE);
right = subString(str,posE + 1, str.length);
return isDigit(left) && isDigit(right);
} else return isDigit(str);
}
static char[] subString(char[] str, int start, int end) {
char sta[] = new char[end - start];
for (int i = start; i < end; i++) {
sta[i - start] = str[i];
}
return sta;
}
}
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
public class Solution {
char cn[] = new char[256];
StringBuffer stringBuffer = new StringBuffer();
public void Insert(char ch) {
++cn[ch];
stringBuffer.append(ch + "");
}
public char FirstAppearingOnce() {
char t[] = stringBuffer.toString().toCharArray();
for(int i=0;i<t.length;i++){
if(cn[t[i]]==1)return t[i];
}
return '#';
}
}
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead.next == null) return null;
ListNode front = pHead;
ListNode fallow = pHead;
while (front.next != null) {
front = front.next;
fallow.next = null;
fallow = front;
}
return front;
}
}
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
/*
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) return null;
ListNode preNode = null;
ListNode node = pHead;
while (node != null) {
if (node.next != null && node.val == node.next.val) {
int value = node.val;
while (node.next != null && node.next.val == value) {
node = node.next;
}
if (preNode == null)
pHead = node.next;
else
preNode.next = node.next;
} else
preNode = node;
node = node.next;
}
return pHead;
}
}
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
/*
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) {
pNode = pNode.right;
while (pNode.left != null) {
pNode = pNode.left;
}
return pNode;
}
while (pNode.next != null) {
if (pNode.next.left == pNode) {
return pNode.next;
}
pNode = pNode.next;
}
return null;
}
}
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if (pRoot == null || pRoot.left == null && pRoot.right == null) return true;
return isSymmetrical(pRoot.left, pRoot.right);
}
boolean isSymmetrical(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
if (left == null || right == null) return false;
if (left.val == right.val)
return isSymmetrical(left.left, right.right) && isSymmetrical(left.right, right.left);
return false;
}
}
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> nodelist = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> result = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
boolean isLeftToRight = true;
int start = 0, end = 1;
if (pRoot == null) return nodelist;
queue.add(pRoot);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
result.add(node.val);
start++;
if (node.left != null) queue.add(node.left);
if (node.right != null) queue.add(node.right);
if (start == end) {
if (!isLeftToRight) nodelist.add(revers(result));
else nodelist.add(result);
//下一行需要改变方向
isLeftToRight = !isLeftToRight;
end = queue.size();
start = 0;
result = new ArrayList<Integer>();
}
}
return nodelist;
}
static ArrayList<Integer> revers(ArrayList<Integer> result) {
ArrayList<Integer> res = new ArrayList<>();
for (int i = result.size() - 1; i >= 0; i--) {
res.add(result.get(i));
}
return res;
}
}
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> resultlist = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> result = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
int start = 0, end = 1;
queue.add(pRoot);
if (pRoot == null) return resultlist;
while (!queue.isEmpty()) {
TreeNode currentNode = queue.poll();
result.add(currentNode.val);
start++;
if (currentNode.left != null) queue.add(currentNode.left);
if (currentNode.right != null) queue.add(currentNode.right);
if (start == end) {
resultlist.add(result);
start = 0;
end = queue.size();
result = new ArrayList<Integer>();
}
}
return resultlist;
}
}