刷题之剑指offer

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值