【剑指offer】11-20题

11.给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。不得使用库函数,不需要考虑大数问题

思路:不能用==比较两个浮点数是否相等,因为有误差。考虑输入值的多种情况。

代码实现

public double Power(double base, int exponent) {
    double res = 0;
    if (equal(base,0)) {
        return 0;
    }
    if (exponent == 0) {
        return 1.0;
    }
    if (exponent > 0) {
        res = mutiply(base,exponent);
    }else {
        res = mutiply(1/base,-exponent);
    }
    return res;
}

public double mutiply(double base, int e) {
    double sum = 1;
    for (int i = 0; i < e; i++) {
        sum = sum * base;
    }
    return sum;
}

public boolean equal(double a, double b) {
    if (a - b < 0.000001 && a - b > -0.000001) {
        return true;
    }
    return false;
}

12.打印1到最大的n位数

思路:考虑大数问题,使用字符串或数组表示。

代码实现

public void printToMaxOfNDigits(int n) {
    int[] array=new int[n];
    if(n <= 0)
        return;
    printArray(array, 0);
}

private void printArray(int[] array,int n) {
    for(int i = 0; i < 10; i++) {
        if(n != array.length) {
            array[n] = i;
            printArray(array, n+1);
        } else {
            boolean isFirstNo0 = false;
            for(int j = 0; j < array.length; j++) {
                if(array[j] != 0) {
                    System.out.print(array[j]);
                    if(!isFirstNo0)
                        isFirstNo0 = true;
                } else {
                    if(isFirstNo0)
                        System.out.print(array[j]);
                }
            }
            System.out.println();
            return ;
        }
    }
}

13.O(1)时间删除链表节点

思路:将要删除节点的下一个节点的值赋给要删除的节点,然后指向下下一个节点

代码实现

public void deleteNode(ListNode head, ListNode deListNode) {
    if (deListNode == null || head == null)
        return;

    if (head == deListNode) {
        head = null;
    } else {
        // 若删除节点是末尾节点,往后移一个
        if (deListNode.nextNode == null) {
            ListNode pointListNode = head;
            while (pointListNode.nextNode.nextNode != null) {
                pointListNode = pointListNode.nextNode;
            }
            pointListNode.nextNode = null;
        } else {
            deListNode.data = deListNode.nextNode.data;
            deListNode.nextNode = deListNode.nextNode.nextNode;
        }
    }
}

14.输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变

思路:每次只和前面一个数交换位置。或者利用辅助数组

代码实现

public void reOrderArray(int [] array) {
    if(array == null)
        return ;

    for(int i = 1; i < array.length; i++){
        int temp = array[i];
        int j = i - 1;
        if(array[i] % 2 != 0){
            while(j >= 0){
                if(array[j] % 2 != 0){
                    break;
                }
                if(array[j]%2 == 0){
                    int t = array[j+1];
                    array[j+1] = array[j];
                    array[j] = t;
                    j--;
                }
            }
        }
        array[j+1] = temp;
    }
}

15.输入一个链表,输出该链表中倒数第k个结点。

扩展题:找中间节点,使用两个指针,一个走一步,一个走两步。找到中间节点

思路:定义一快一慢两个指针,快指针走K步,然后慢指针开始走,快指针到尾时,慢指针就找到了倒数第K个节点。

代码实现

public ListNode FindKthToTail(ListNode head,int k) {
    if (head == null || k <= 0) {
        return null;
    }
    ListNode fast = head;
    ListNode slow = head;
    while(k-- > 1) {
        if (fast.next != null)
            fast = fast.next;
        else
            return null;
    }
    while (fast.next != null) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

16.输入一个链表,反转链表后,输出链表的所有元素。

扩展题:输出反转后链表的头节点,定义三个指针反向输出。

思路:定义两个指针,反向输出

代码实现

public ListNode ReverseList(ListNode head) {
    if (head == null) {
        return null;
    }
    ListNode temp = null;
    while(head != null) {
        ListNode p = head.next;
        head.next = temp;
        temp = head;
        head = p;
    }
    return temp;
}

17.输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

思路:递归与非递归求解,小数放在前面。

代码实现

public ListNode Merge(ListNode list1,ListNode list2) {
    if (list1 == null) {
        return list2;
    }
    if (list2 == null) {
        return list1;
    }
    ListNode newHead = null;
    if (list1.val <= list2.val) {
        newHead = list1;
        newHead.next = Merge(list1.next,list2);
    }else {
        newHead = list2;
        newHead.next = Merge(list1,list2.next);
    }

    return newHead;
}

18.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路:若根节点相等,利用递归比较他们的子树是否相等,若根节点不相等,则利用递归分别在左右子树中查找。

代码实现

public boolean HasSubtree(TreeNode root1,TreeNode root2) {
    boolean result = false;

    if (root2 != null && root1 != null) {
        if(root1.val == root2.val){
            result = doesTree1HaveTree2(root1,root2);
        }
        if (!result)
            return HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2);
    }
    return result;
}

public boolean doesTree1HaveTree2(TreeNode node1, TreeNode node2) {
    if (node2 == null) {
        return true;
    }
    if (node1 == null) {
        return false;
    }
    if (node1.val != node2.val) {
        return false;
    }
    return doesTree1HaveTree2(node1.left,node2.left) && 
                doesTree1HaveTree2(node1.right,node2.right);
}

19.操作给定的二叉树,将其变换为源二叉树的镜像。

思路:使用递归或非递归方式交换每个节点的左右子树位置。

代码实现

public void Mirror(TreeNode root) {
    if (root == null) {
        return;
    }

    Stack<TreeNode> stack = new Stack<>();
    while (root != null || !stack.isEmpty()) {
        while (root != null) {
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            stack.push(root);
            root = root.left;
        }
        if (!stack.isEmpty()) {
            root = stack.pop();
            root = root.right;
        }
    }
}

20.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

思路:终止行号大于起始行号,终止列号大于起始列号,

代码实现

public ArrayList<Integer> printMatrix(int[][] matrix) {
    ArrayList<Integer> list = new ArrayList<>();
    if(matrix == null)
        return list;
    int start = 0;
    while(matrix[0].length > start*2 && matrix.length > start*2) {
        printOneCircle(matrix,start,list);
        start++;
    }
    return list;
}


private void printOneCircle(int[][] matrix,int start,ArrayList<Integer> list) {
    int endX = matrix[0].length - 1 - start; // 列
    int endY = matrix.length - 1 - start;  // 行
    // 从左往右
    for (int i = start; i <= endX; i++)
        list.add(matrix[start][i]);
    // 从上往下
    if (start < endY) {
        for (int i = start + 1; i <= endY; i++)
            list.add(matrix[i][endX]);
    }
    // 从右往左(判断是否会重复打印)
    if (start < endX && start < endY) {
        for (int i = endX - 1; i >= start; i--)
            list.add(matrix[endY][i]);
    }
    // 从下往上(判断是否会重复打印)
    if (start < endX && start < endY - 1) {
        for (int i = endY - 1; i >= start + 1; i--)
            list.add(matrix[i][start]);
    }
}

未完待续。。。。。

作者:白夜行515 链接:https://blog.csdn.net/baiye_xing/article/details/78428561

    原文作者: 白夜行515
    原文地址: https://blog.csdn.net/baiye_xing/article/details/78428338
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞