【剑指offer】11-20题

来源:互联网 发布:犹大福音 知乎 编辑:程序博客网 时间:2024/06/10 19:28

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]);    }}

未完待续。。。。。

原创粉丝点击