剑指offer——1

  1. 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
    矩阵是有序的,从左下角来看,向上数字递减,向右数字递增,
    因此从左下角开始查找,当要查找数字比左下角数字大时。右移
    要查找数字比左下角数字小时,上移。这样找的速度最快。

    代码实现是由左下角开始找
public boolean Find(int target, int [][] array) {
        //基本思路从左下角开始找,这样速度最快
       int row = array.length-1;//行
        int column = 0;//列
        //当行数大于0,当前列数小于总列数时循环条件成立
        while((row >= 0)&& (column< array[0].length)){
            if(array[row][column] > target){
                row--;
            }else if(array[row][column] < target){
               column++;
            }else{
                return true;
            }
        }
        return false;
    }
  1. 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
  /**
     * 第一种方法:常规方法。利用String.charAt(i)以及String.valueOf(char).equals(" "
     * )遍历字符串并判断元素是否为空格。是则替换为"%20",否则不替换
     */
    public  String replaceSpace(StringBuffer str) {

        int length = str.length();
        // System.out.println("length=" + length);
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < length; i++) {
            char b = str.charAt(i);
            if (String.valueOf(b).equals(" ")) {
                result.append("%20");
            } else {
                result.append(b);
            }
        }
        return result.toString();

    }

  1. 输入一个链表,从尾到头打印链表每个节点的值
    思路:借助栈实现,或使用递归的方法
 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        if (listNode == null)
            return list;
        Stack<ListNode> stack = new Stack<>();
        while (listNode != null) {
            stack.push(listNode);
            listNode = listNode.next;
        }

        while (!stack.isEmpty()) {
            list.add(stack.pop().val);
        }
        return list;
    }

  1. 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
     思路:在二叉树的前序遍历序列中,第一个数字总是树的根结点的值。但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边。因此我们需要扫描中序遍历序列,才能找到根结点的值。
     如下图所示,前序遍历序列的第一个数字1就是根结点的值。扫描中序遍历序列,就能确定根结点的值的位置。根据中序遍历特点,在根结点的值1前面的3个数字都是左子树结点的值,位于1后面的数字都是右子树结点的值。
     在这里插入图片描述
public static class TreeNode {
         int val;
         TreeNode left;
         TreeNode right;
         TreeNode(int x) { val = x; }
     }
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if (pre == null || in == null) {
            return null;
        }
        if (pre.length == 0 || in.length == 0) {
            return null;
        }
        if (pre.length != in.length) {
            return null;
        }
        TreeNode root = new TreeNode(pre[0]);
        for (int i = 0; i < pre.length; i++) {
            if (pre[0] == in[i]) {
                root.left = reConstructBinaryTree(
                                Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
                root.right = reConstructBinaryTree(
                Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
            }
        }
        return root;
    }

  1. 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
    思路:一个栈压入元素,而另一个栈作为缓冲,将栈1的元素出栈后压入栈2中。也可以将栈1中的最后一个元素直接出栈,而不用压入栈2中再出栈。
 public void push(int node) {
        stack1.push(node);
    }

    public int pop() throws Exception {
        if (stack1.isEmpty() && stack2.isEmpty()) {
            throw new Exception("栈为空!");
        }

        if (stack2.isEmpty()) {
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

  1. 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0

    改题由于自己思考错误,存在问题,后续带来详细解答

  2. 现在要求输入一个整数n,请你输出斐波那契数列的第n项
    采用递归:

public int Fibonacci(int n) {

            if (n <= 0) {
                return 0;
            }
            if (n == 1||n==2) {
                return 1;
            }

            return Fibonacci(n - 2) + Fibonacci(n - 1);

        }

采用迭代法:

  int Fibonacci(int number) {
            if (number <= 0) {
                return 0;
            }
            if (number == 1 || number == 2) {
                return 1;
            }
            int first = 1, second = 1, third = 0;
            for (int i = 3; i <= number; i++) {
                third = first + second;
                first = second;
                second = third;
            }
            return third;
        }

  1. 跳台阶问题
    题目描述:
    一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
    问题分析:
    正常分析法:
    a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);
    b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
    c.由a,b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
    d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
    找规律分析法:
    f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5, 可以总结出f(n) = f(n-1) + f(n-2)的规律。
    但是为什么会出现这样的规律呢?假设现在6个台阶,我们可以从第5跳一步到6,这样的话有多少种方案跳到5就有多少种方案跳到6,另外我们也可以从4跳两步跳到6,跳到4有多少种方案的话,就有多少种方案跳到6,其他的不能从3跳到6什么的啦,所以最后就是f(6) = f(5) + f(4);这样子也很好理解跳台阶的问题了。
    所以这道题其实就是斐波那契数列的问题。
    代码只需要在上一题的代码稍做修改即可。
int jumpFloor(int number) {
            if (number <= 0) {
                return 0;
            }
            if (number == 1) {
                return 1;
            }
            if (number == 2) {
                return 2;
            }
            int first = 1, second = 2, third = 0;
            for (int i = 3; i <= number; i++) {
                third = first + second;
                first = second;
                second = third;
            }
            return third;
        }

变态跳台阶问题
题目描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

问题分析:
假设n>=2,第一步有n种跳法:跳1级、跳2级、到跳n级
跳1级,剩下n-1级,则剩下跳法是f(n-1)
跳2级,剩下n-2级,则剩下跳法是f(n-2)
……
跳n-1级,剩下1级,则剩下跳法是f(1)
跳n级,剩下0级,则剩下跳法是f(0)
所以在n>=2的情况下:
f(n)=f(n-1)+f(n-2)+…+f(1)
因为f(n-1)=f(n-2)+f(n-3)+…+f(1)
所以f(n)=2*f(n-1) 又f(1)=1,所以可得f(n)=2^(number-1)

 int JumpFloorII(int number) {
        return 1 << --number;//2^(number-1)用位移操作进行,更快
    }
`补充:
java中有三种移位运算符: 
1. << : 左移运算符,等同于乘2的n次方 
2. >>: 右移运算符,等同于除2的n次方 
3. >>> 无符号右移运算符,不管移动前最高位是0还是1,右移后左侧产生的空位部分都以0来填充。与>>类似。 
例: 
int a = 16; 
int b = a << 2;//左移2,等同于16 * 2的2次方,也就是16 * 4 
int c = a >> 2;//右移2,等同于16 / 2的2次方,也就是16 / 4


猜你喜欢

转载自blog.csdn.net/qq_39411208/article/details/88287484
今日推荐