1.二维数组中的查找
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
public class Solution_p38 {
public boolean Find(int target, int [][] array) {
int m = array.length; //m行
int n = array[0].length; //n列
int i = 0;
while ((i < m) & (n > 0)){ //数组不为空时
if (array[i][n-1] > target)
n--;
else if (array[i][n-1] < target)
i++;
else return true;
}
return false;
}
思路:从右上角开始比较,逐渐剃掉行,列。
2.替换空格
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
public class Solution_p44 {
public static void main(String[] args){
//用java自带的插入函数append
Solution_p44 s = new Solution_p44();
StringBuffer str = new StringBuffer("hello world");
String str_return = s.replaceSpace(str);
System.out.println(str_return);
}
public String replaceSpace(StringBuffer str) {
StringBuffer str_new = new StringBuffer();
for(int i = 0; i < str.length(); i++){
if(str.charAt(i) == ' '){
str_new.append("%20");
}
else{
str_new.append(str.charAt(i));
}
}
return str_new.toString();
/* //用c++的思想
* String str_new = str.toString();
char[] strChar = str_new.toCharArray();
int spacenum = 0;
for(int i = 0; i < strChar.length; i++){
if(strChar[i] == ' '){
spacenum++;
}
}
int newlength = strChar.length + (spacenum * 2);
int j = newlength - 1;
int i = strChar.length - 1;
char[] strChar_new = new char[newlength];
while(i >= 0){
if(strChar[i] == ' '){
strChar_new[j] = '0';
strChar_new[j-1] = '2';
strChar_new[j-2] = '%';
j -= 3;
i--;
}
else {
strChar_new[j] = strChar[i];
i--;
j--;
}
}
return String.valueOf(strChar_new);
*/
}
}
思路:第一种方法使用java自带的函数,
str.charAt(i)获取字符串中索引为i的字符,
str_new.append(str.charAt(i))在str_new后加入str.charAt(i),
str_new.toString()将StringBuffer类型的str_new转化为String类型。
第二种方法使用c++的思想,先计算出空格的个数,再将字符串倒叙复制到新的字符串中,同时将空格替换成20%,
如果正序复制的话,就不需要计算空格的个数了,直接复制,遇到旧字符串是空格时,在新的字符串中加上20%,
由于char数组在new时是多长,就只能用这么长的空间,所以不能在旧字符串上直接修改,那样会提醒字符数组索引超出范围。
本题的c语言解法提供了足够长的char数组,所以,可以在旧的字符上直接修改。
String.valueOf(strChar_new)是将字符数组转化为String类型的函数。
问题:
1.StringBuffer类是什么?
2.String类可以使用charAt(i),append吗?
3.1从尾到头打印链表(栈)
熟悉ArrayList的使用方法
//剑指offer,p52,从尾到头打印链表
package jianzhioffer;
import java.util.ArrayList;
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public class Solution_p52 {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ListNode point = listNode;
int N = 0;
while(point != null){
push(point.val);
point = point.next;
N++;
}
ArrayList<Integer> list = new ArrayList<Integer>(N);
for(int i = 0; i < N; i++){
list.add(pop());
}
return list;
}
private ListNode top;
private void push(int a){
ListNode oldtop = top;
top = new ListNode(a);
top.next = oldtop;
}
private int pop(){
int val = top.val;
top = top.next;
return val;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ListNode test_3 = new ListNode(3);
ListNode test_2 = new ListNode(2);
ListNode test_1 = new ListNode(1);
test_3.next = test_2;
test_2.next = test_1;
Solution_p52 test = new Solution_p52();
ArrayList<Integer> result = test.printListFromTailToHead(test_3);
}
}
3.2从尾到头打印链表(递归)
//剑指offer,p52,从尾到头打印链表,递归方法
package jianzhioffer;
import java.util.ArrayList;
public class Solution_p52_2 {
public ArrayList<Integer> list = new ArrayList<Integer>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if(listNode != null){
printListFromTailToHead(listNode.next);
list.add(listNode.val);
}
return list;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ListNode test_3 = new ListNode(3);
ListNode test_2 = new ListNode(2);
ListNode test_1 = new ListNode(1);
test_3.next = test_2;
test_2.next = test_1;
Solution_p52 test = new Solution_p52();
ArrayList<Integer> result = test.printListFromTailToHead(test_3);
}
}
4.重建二叉树
(记忆方式:按照根节点的遍历顺序记忆)
前序遍历:根节点-左结点-右结点
中序遍历:左结点-根节点-右结点
后序遍历:左结点-右结点-根节点
//剑指offer,p55,重建二叉树,递归方法
package jianzhioffer;
import java.util.*;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
this.val = x;
}
}
public class Solution_p55 {
public TreeNode reConstructBinaryTree(int [] pre, int [] in) {
int N_pre = pre.length;
int N_in = in.length;
if(N_pre == 0 || N_in == 0) return null;
TreeNode tree = new TreeNode(pre[0]);
int i = 0;
for(; i < N_in; i++){//找出pre的第一个元素在in中的位置
if (in[i] == pre[0])
break;
}
tree.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+1), Arrays.copyOfRange(in, 0, i));
tree.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i+1, N_pre), Arrays.copyOfRange(in, i+1, N_in));
return tree;
}
}
5.用两个栈实现队列
//剑指offer,p59,用两个栈实现队列
package jianzhioffer;
import java.util.Stack;
public class Solution_p59 {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack2.size() != 0) return stack2.pop();//先检验第二个栈是否为空
while(stack1.size() != 0){
stack2.push(stack1.pop());
}
return stack2.pop();
}
}
//剑指offer,旋转数组的最小数字,p66
package jianzhioffer;
public class Solution_p66 {
public int minNumberInRotateArray(int [] array) {
if(array.length == 0) return 0;
int lo = 0;
int hi = array.length - 1;
int mid = lo;//令mid = lo,当数组顺序排列时,不需要经过下面的while循环就可找到最小值
while(array[lo] >= array[hi]){
if((hi-lo) == 1){
mid = hi;
break;
}
mid = (lo + hi)/2;
if(array[lo] == array[hi] && array[mid] == array[hi])
return MinInOrder(array);
if(array[mid] <= array[hi]){
hi = mid;
}
else if(array[mid] >= array[lo]){
lo = mid;
}
}
return array[mid];
}
public int MinInOrder(int[] a){
int N = a.length;
for(int i = 1; i < N; i++){
if(a[0] > a[i]){
int temp = a[0];
a[0] = a[i];
a[i] = temp;
}
}
return a[0];
}
}
//剑指offer,斐波那契数列,p73
package jianzhioffer;
public class Solution_p73 {
public int Fibonacci(int n) {
if(n <= 0) return 0;
if(n == 1) return 1;
int f_1 = 1;
int f_2 = 0;
int f = 0;
for(int i = 2; i <= n; i++){
f = f_1 + f_2;
f_2 = f_1;
f_1 = f;
}
return f;
}
}
//剑指offer,青蛙跳台阶,p75
package jianzhioffer;
public class Solution_p75 {
public int JumpFloor(int target) {
//if(target <= 0) return 0;
if(target == 1) return 1;
if(target == 2) return 2;
int f_1 = 2;
int f_2 = 1;
int f = 0;
while(target >= 3){
f = f_1 + f_2;
f_2 = f_1;
f_1 = f;
target--;
}
return f;
}
}
//剑指offer,青蛙跳台阶(升级版),p76
package jianzhioffer;
public class Solution_p76 {
public int JumpFloorII(int target) {
return (int)java.lang.Math.pow(2, target-1);
}
}
//剑指offer,矩形覆盖,p77
package jianzhioffer;
public class Solution_p77 {
public int JumpFloor(int target) {
//if(target <= 0) return 0;
if(target == 1) return 1;
if(target == 2) return 2;
int f_1 = 2;
int f_2 = 1;
int f = 0;
while(target >= 3){
f = f_1 + f_2;
f_2 = f_1;
f_1 = f;
target--;
}
return f;
}
}
//剑指offerp81,二进制中1的个数
package jianzhioffer;
public class Solution_p81 {
public int NumberOf1(int n) {
int count = 0;
while(n != 0){
count++;
n = (n - 1) & n;
}
return count;
}
}
//剑指offerp90,数值的整数次方
package jianzhioffer;
public class Solution_p90 {
public double Power(double base, int exponent) {
//底数为0,指数小于0
if((base == 0.0) && (exponent < 0)){//base == 0.0
return 0;//0.0
}
int abse ; //指数的绝对值
if(exponent < 0){
abse = -exponent;
}else{
abse = exponent;
}
double result = 1.0;
//第一种方法
/*for(int i = 0; i < abse; i++){
result *= base;
}*/
//第二种,循环
if(abse == 0)return 1.0;
if(abse == 1)return base;
for(int n = 2; n <= abse; n = n * 2){
double a = base;
result = a * a;
a = result;
}
if(abse%2 != 0){
result = result * base;
}
//第二种(2),循环
/*if(abse == 0)return 1.0;
if(abse == 1)return base;
for(int i = 2; i <= abse; i++){
double result_oushu = base * base;
double result_jishu = base * base *base;
double a = base;
if(i%2 == 0){
result_oushu = a*a;
a = result_oushu;
}
if(i%2 != 0){
result_jishu = a * a * base;
}
if(abse%2 == 0){result = result_oushu;}
else {result = result_jishu;}
}*/
//第三种,递归
/*if(abse == 0)return 1.0;
if(abse == 1)return base;
result = Power(base, abse>>1);//右移除以2
result *= result;
if (abse%2 != 0){result = result * base;}*/
if(exponent < 0) result = 1.0 / result;
return result;
}
}
//剑指offerp102, 调整数组顺序使奇数位于偶数前面
package jianzhioffer;
public class Solution_p102 {
public static void reOrderArray(int [] array) {
int count = 0;
int i = 0;
while (count < array.length)
{
if (array[i]%2 != 0) i++;
else if (array[i]%2 == 0)
{
int temp = array[i];
for (int j=i; j<array.length-1; j++)
{
array[j] = array[j+1];
}
array[array.length-1] = temp;
}
count++;
}
}
public static void main(String[] args)
{
int[] a = {1,2,3,4,5,6,7};
reOrderArray(a);
for(int i=0; i<a.length; i++)
{
System.out.println(a[i]);
}
}
}
//剑指offerp107, 链表中倒数的第k个结点
package jianzhioffer;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution_p107 {
public ListNode FindKthToTail(ListNode head,int k) {
if((head == null) || (k == 0))
return null;
ListNode first = new ListNode(1);
first.next = head;
ListNode second = new ListNode(2);
second.next = head;
for(int i=0; i<k-1; i++)
{
if(first.next.next != null) first.next = first.next.next;
else return null; //k大于结点数量
}
while(first.next.next != null)
{
first.next = first.next.next;
second.next = second.next.next;
}
return second.next;
}
}
//剑指offerp112,反转链表
package jianzhioffer;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution_p112 {
public ListNode ReverseList(ListNode head) {
if(head == null) return null;
if(head.next == null) return head; //至少要有两个节点
ListNode a = new ListNode(1);
a.next = head;
ListNode b = new ListNode(2);
b.next = head.next;
ListNode c = new ListNode(3);
c.next = head.next.next;
head.next = null;
while(c.next != null) {
b.next.next = a.next;
a.next = b.next;
b.next = c.next;
c.next = c.next.next;
}
b.next.next = a.next;
a.next = b.next;
return a.next;
}
}
//剑指offerp114,合并两个排序的链表
package jianzhioffer;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution_p114 {
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1 == null) return list2;
else if(list2 == null) return list1;
ListNode head = new ListNode(1);
if(list1.val >= list2.val){
head = list2;
head.next = Merge(list1, list2.next);
}
else {
head = list1;
head.next = Merge(list1.next, list2);
}
return head;
}
}
剑指offerp117,树的子结构
package jianzhioffer;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution_p117 {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
boolean result = false;
if((root1 != null)&&(root2 != null)) {
if(root1.val == root2.val) {
result = DoseTree1HasTree2(root1, root2);
}
if(!result) {
result = HasSubtree(root1.left, root2);
}
if(!result) {
result = HasSubtree(root1.right, root2);
}
}
return result;
}
private boolean DoseTree1HasTree2(TreeNode root1, TreeNode root2) {
if(root2 == null) return true;
if(root1 == null) return false;
if(root1.val != root2.val) return false;
return DoseTree1HasTree2(root1.left, root2.left) && DoseTree1HasTree2(root1.right, root2.right);
}
}
//剑指offerp125,二叉树的镜像
package jianzhioffer;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution_p125 {
public void Mirror(TreeNode root) {
if(root == null) return;
if((root.left != null) || (root.right != null)) {
exch(root);//此处需要注意,需要将root传递给exch函数,
//而不是将root.left和root.right传递给exch函数。
//TreeNode temp = root.left;
//root.left = root.right;
//root.right = temp;
Mirror(root.left);
Mirror(root.right);
}
}
private void exch(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
//剑指offer,p127,顺时针打印矩阵
package jianzhioffer;
import java.util.ArrayList;
public class Solution_p127
{
public static ArrayList<Integer> printMatrix(int[][] array)
{
if(array == null) return null;
int n = array.length; //m行
int m = array[0].length; //n列
int start = 0;
ArrayList<Integer> result = new ArrayList<Integer>();
while(m > 2*start && n > 2*start) {
int endx = m - 1 - start; //终止列
int endy = n - 1 - start; //终止行
for(int i = start; i <= endx; i++) //画第一步
{
result.add(array[start][i]);
System.out.println(array[start][i]);
}
if(endy > start) //画第二步
{
for(int i = start + 1; i <= endy; i++)
{
result.add(array[i][endx]);
System.out.println(array[i][endx]);
}
}
if(endy > start && endx > start) //画第三步
{
for(int i = endx - 1; i >= start; i--)
{
result.add(array[endy][i]);
System.out.println(array[endy][i]);
}
}
if(endx > start && (endy - start) > 1 ) //画第四步
{
for(int i = endy - 1; i >= start + 1; i--)
{
result.add(array[i][start]);
System.out.println(array[i][start]);
}
}
start++;
}
return result;
}
public static void main(String[] args)
{
int[][] a= {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}};
printMatrix(a);
}
}
//剑指offer,p132,包含min函数的栈
package jianzhioffer;
import java.util.Stack;
public class Solution_p132 {
Stack<Integer> a = new Stack<Integer>();
Stack<Integer> b = new Stack<Integer>(); //辅助栈
public void push(int node) {
a.push(node);
if (b.size() == 0) b.push(node);
else if(node < min()) b.push(node);
else b.push(min());
}
public void pop() {
if(a.size() == 0 || b.size() == 0) return;
a.pop();
b.pop();
}
public int top() {
return b.peek();
}
public int min() {
return top();
}
}
//剑指offer,p134,栈的压入、弹出序列
package jianzhioffer;
import java.util.ArrayList;
import java.util.Stack;
public class Solution_p134 {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA == null || popA == null || pushA.length == 0 || popA.length == 0) return false;
Stack<Integer> s = new Stack<Integer>();
int index = 0; //popA序列的索引
for(int i = 0; i < pushA.length; i++) //遍历pushA序列
{
s.push(pushA[i]); //先将pushA第一个元素放入辅助栈
while(!s.empty() && popA[index] == s.peek()) //比较辅助栈栈顶元素与popA序列元素关系,如相等,辅助栈出栈,popA序列右移一位,再比较栈顶与popA序列
{ //如不等,继续将pushA序列入栈,直到全部入栈。
s.pop();
index++;
}
}
return s.empty(); //返回辅助栈是否为空,如果为空,popA序列是pushA序列的出栈顺序,否则不是
}
}
//剑指offerp137,从上往下打印二叉树
package jianzhioffer;
import java.util.ArrayList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.Queue;
import java.util.LinkedList;
public class Solution_p137 {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(root == null) return list;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root); //将根节点放入队列中
while(!queue.isEmpty())
{
root = queue.poll(); //出队的结点作为新的根节点
list.add(root.val);
if(root.left != null) queue.offer(root.left);
if(root.right != null) queue.offer(root.right);
}
return list;
}
}
//剑指offerp140,二叉搜索树的后序遍历序列
package jianzhioffer;
public class Solution_p140 {
public boolean VerifySquenceOfBST(int [] sequence) {
if(sequence == null || sequence.length == 0) return false;
else return VerifySquenceOfBST(sequence, 0, sequence.length-1);
}
public boolean VerifySquenceOfBST(int [] sequence, int startindex, int endindex) {
if(endindex <= startindex) return true;
int root = sequence[endindex];
int i = startindex;
for(; i < endindex; i++)
{
if (sequence[i] > root)
break;
}
int j = i;
for(; j < endindex; j++)
{
if (sequence[j] < root)
return false;
}
boolean left = true;
left = VerifySquenceOfBST(sequence, startindex, i-1);
boolean right = true;
right = VerifySquenceOfBST(sequence, i, endindex-1);
return (right && left);
}
}
//剑指offer,p143,二叉树中和为某一值的路径
package jianzhioffer;
import java.util.ArrayList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution_p143 {
private ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>();
private ArrayList<Integer> list = new ArrayList<Integer>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target){
if (root == null) return listAll;
int sum = 0;
sum += root.val;
list.add(root.val);
if(root.left == null && root.right == null && sum == target)
{
listAll.add(new ArrayList<Integer>(list));
}
FindPath(root.left, target-sum);
FindPath(root.right, target-sum);
list.remove(list.size()-1);
return listAll;
}
}