【剑指offer】手撕代码(2)

11、求一个数的整数次方

public class Test{
    public double power(double base,int exponent) throws Exception {
        double result = 0.0;
        //第一种情况
        if ((base == 0.0)&& (exponent<0)){
            throw new Exception("0的负数次幂没有意义");
        }
        //如果是负数次方
        if (exponent<0){
            result = 1.0/powerWithExponent(base,-exponent);
        }else {
            result = powerWithExponent(base,exponent);
        }
        return result;
    }
    private double powerWithExponent(double base, int exponent) {
        if (exponent==0)
            return 1;
        if (exponent==1)
            return base;
        double result = 1.0;
        for (int i=1;i<=exponent;i++){
            result = result*base;
        }
        return result;
    }
    public static void main(String[] args) throws Exception {
        Test test = new Test();
        System.out.println(test.power(2.0,5));
    }
}

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

  • 比如输入n=3,打印1~999
public class Test{
    public void printToMaxOfNDigits(int n){
        StringBuffer sb = new StringBuffer();
        for (int i=0;i<n;i++){
            sb.append(9);
        }
        //将StringBuffer类型转为String型
        String s = new String(sb);
        //将String型转为int型
        int num = Integer.valueOf(s).intValue();
        for (int j=1;j<=num;j++){
            System.out.print(j+" ");
        }



    }
    public static void main(String[] args) {
        Test test = new Test();
        test.printToMaxOfNDigits(3);
    }
}

13、在O(1)时间内删除链表结点

  • 给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点
class ListNode{
    int data;
    ListNode nextNode;
}
public class Test{
    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;
                //只要头节点后面连续两个节点不为空即节点个数大于4
                while (pointListNode.nextNode.nextNode != null){
                    pointListNode = pointListNode.nextNode;
                }
                pointListNode.nextNode=null;
            }else {
                //删除一般位置的节点
                deListNode.data = deListNode.nextNode.data;
                deListNode.nextNode = deListNode.nextNode.nextNode;
            }
        }
    }
    public static void main(String[] args) {
        ListNode head = new ListNode();
        ListNode second = new ListNode();
        ListNode third = new ListNode();
        head.nextNode=second;
        second.nextNode=third;
        head.data=1;
        second.data=2;
        third.data=3;
        Test test = new Test();
        //传入头节点,要删除第二个节点
        test.deleteNode(head,second);
        //结果为3
        System.out.println(head.nextNode.data);
    }
}

14、调整数组

  • 使所有的奇数在前半部分,偶数在后半部分
public class Test{
    public void order(int[] arr){
        //判断数组是否为空
        if (arr==null || arr.length==0)
            return;
        int start = 0;
        int end = arr.length-1;
        while (start<end){
            //根据奇数偶数做不同处理
            //是奇数,继续向后找
            while (!isEven(arr[start]))
                start++;
            //是偶数,继续向前找
            while (isEven(arr[end]))
                end--;
            //交换当前找到的奇数和偶数进行交换
            if (start<end){
                int temp = arr[start];
                arr[start] = arr[end];
                arr[end] = temp;
            }
        }
    }

    private boolean isEven(int i) {
        return i%2==0;
    }
    public static void main(String[] args) {
        Test test = new Test();
        int[] arr = {2,3,1,4,8,5,6,0};
        test.order(arr);
        System.out.println(Arrays.toString(arr));
    }
}

15、求链表中的倒数第K个节点

  • 从1开始对节点计数
class ListNode{
    int data;
    ListNode nextNode;
}
public class Test{
    public ListNode findKToTail(ListNode head,int k){
        //如果链表为空,直接返回空
        if (head==null || k==0)
            return null;
        //定义一个查找到的结果节点和一个临时指向节点
        ListNode resultNode = null;
        ListNode headListNode = head;
        //控制headListNode位置
        for (int i = 0; i < k; i++) {
            if (headListNode.nextNode!=null)
                headListNode = headListNode.nextNode;
            else
                return null;
        }
        resultNode = head;
        //用headListNode.nextNode是否为空,来决定resultNode用头节点向后移几个
        while (headListNode!=null){
            resultNode = resultNode.nextNode;
            headListNode = headListNode.nextNode;
        }
        return resultNode;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode();
        ListNode second = new ListNode();
        ListNode third = new ListNode();
        ListNode forth = new ListNode();
        head.nextNode = second;
        second.nextNode = third;
        third.nextNode = forth;
        head.data=1;
        second.data=2;
        third.data=3;
        forth.data=4;
        Test test = new Test();
        //求倒数第三个节点,即second,值为2
        System.out.println(test.findKToTail(head,3).data);
    }
}

16、求一个链表的反转(链表逆置)

  • 输入一个链表的头节点,输出反转后链表的头节点
class ListNode{
    int data;
    ListNode nextNode;
}
public class Test{
    public ListNode reverseList(ListNode head){
        if (head==null)
            return null;
        if (head.nextNode==null)
            return head;
        ListNode pre = null;
        ListNode now = head;
        ListNode reversedHead = null;
        while (now.nextNode!=null){
            ListNode next = now.nextNode;
            if (next==null)
                reversedHead = next;
            now.nextNode=pre;
            pre=now;
            now=next;
        }
        return now;
    }
    public static void main(String[] args) {
        ListNode head = new ListNode();
        ListNode second = new ListNode();
        ListNode third = new ListNode();
        ListNode forth = new ListNode();
        head.nextNode = second;
        second.nextNode = third;
        third.nextNode = forth;
        head.data=1;
        second.data=2;
        third.data=3;
        forth.data=4;
        Test test = new Test();
        //反转链表的头节点为forth,值为4
        System.out.println(test.reverseList(head).data);
    }
}

17、合并两个已经排好序的增序链表,要求合并好仍为增序

class ListNode{
    int data;
    ListNode nextNode;
}
public class Test{
    public ListNode mergeList(ListNode head1,ListNode head2){
        if (head1==null)
            return head2;
        else if (head2==null)
            return head1;
        ListNode mergeHead = null;
        if(head1.data < head2.data){
            mergeHead = head1;
            mergeHead.nextNode = mergeList(head1.nextNode,head2);
        }else {
            mergeHead = head2;
            mergeHead.nextNode = mergeList(head1,head2.nextNode);
        }
        return mergeHead;
    }

    public static void main(String[] args) {
        ListNode head1 = new ListNode();
        ListNode head2 = new ListNode();
        ListNode second1 = new ListNode();
        ListNode second2 = new ListNode();
        ListNode third1 = new ListNode();
        head1.nextNode = second1;
        second1.nextNode = third1;
        head2.nextNode = second2;
        head1.data=1;
        second1.data=3;
        head2.data=2;
        second2.data=4;
        third1.data=5;
        Test test = new Test();
        //程序返回的是新链表的头节点,此处看其最后一个值
        System.out.println(test.mergeList(head1,head2).nextNode.nextNode.nextNode.nextNode.data);
    }
}

18、树的子结构

  • 输入两颗二叉树A和B,判断B是否为A的子结构
class BinaryTreeNode{
    int value;
    BinaryTreeNode leftNode;
    BinaryTreeNode rightNode;
}
public class Test{
    public boolean hasSubTree(BinaryTreeNode root1,BinaryTreeNode root2){
        boolean result = false;
        if(root1!=null && root2!=null){
            if (root1.value == root2.value){
                result = doesTree1HaveTree2(root1,root2);
                if (!result)
                    result = hasSubTree(root1.leftNode,root2);
                if (!result)
                    result = hasSubTree(root1.rightNode,root2);
            }
        }
        return result;
    }

    private boolean doesTree1HaveTree2(BinaryTreeNode root1, BinaryTreeNode root2) {
        if (root2==null)
            return true;
        else if (root1==null)
            return false;
        if (root1.value==root2.value)
            return false;
        return doesTree1HaveTree2(root1.leftNode,root2.leftNode) &&
                doesTree1HaveTree2(root1.rightNode,root2.rightNode);
    }

    public static void main(String[] args) {
        BinaryTreeNode root1 = new BinaryTreeNode();
        BinaryTreeNode node1 = new BinaryTreeNode();
        BinaryTreeNode node2 = new BinaryTreeNode();
        BinaryTreeNode node3 = new BinaryTreeNode();
        BinaryTreeNode node4 = new BinaryTreeNode();
        BinaryTreeNode node5 = new BinaryTreeNode();
        BinaryTreeNode node6 = new BinaryTreeNode();
        BinaryTreeNode root2 = new BinaryTreeNode();
        BinaryTreeNode a = new BinaryTreeNode();
        BinaryTreeNode b = new BinaryTreeNode();
        root1.leftNode=node1;
        root1.rightNode=node2;
        node1.leftNode=node3;
        node1.rightNode=node4;
        node4.leftNode=node5;
        node4.rightNode=node6;
        root1.value=8;
        node1.value=8;
        node2.value=7;
        node3.value=9;
        node4.value=2;
        node5.value=4;
        node6.value=7;
        root2.leftNode=a;
        root2.rightNode=b;
        root2.value=8;
        a.value=9;
        b.value=2;
        Test test = new Test();
        System.out.println(test.hasSubTree(root1,root2));
    }
}

19、镜像二叉树

  • 求一个二叉树的镜像,即将左右子节点交换
class BinaryTreeNode{
    BinaryTreeNode leftNode;
    BinaryTreeNode rightNode;
    int value;
}
public class Test{
    public BinaryTreeNode mirrorBinaryTree(BinaryTreeNode root){
        //根节点为空
        if (root==null)
            return null;
        //根节点的左右节点不存在
        if (root.leftNode==null && root.rightNode==null)
            return null;
        //定义栈来存放数据
        Stack<BinaryTreeNode> stack = new Stack<>();
        //只要root不为空或者栈不为空就进入循环
        while (root!=null || !stack.isEmpty()){
            //二叉树的左右节点交换
            BinaryTreeNode temp = root.leftNode;
            root.leftNode = root.rightNode;
            root.rightNode = temp;
            //将当前根节点存入栈 先入后出
            stack.push(root);
            //更改根节点
            root = root.leftNode;
        }
        //出栈
        root = stack.pop();
        root = root.rightNode;
        return root;
    }

    public static void main(String[] args) {
        BinaryTreeNode root = new BinaryTreeNode();
        BinaryTreeNode node1 = new BinaryTreeNode();
        BinaryTreeNode node2 = new BinaryTreeNode();
        BinaryTreeNode node3 = new BinaryTreeNode();
        BinaryTreeNode node4 = new BinaryTreeNode();
        root.leftNode = node1;
        root.rightNode = node2;
        node1.leftNode = node3;
        node1.rightNode = node4;
        root.value = 1;
        node1.value = 2;
        node2.value = 3;
        node3.value = 4;
        node4.value = 5;
        Test test = new Test();
        //结果应该是5
        System.out.println(test.mirrorBinaryTree(root).leftNode.rightNode.value);
    }
}

20、顺时针打印矩阵

  • 按从外到里顺时针的顺序依次打印每个数字
public class Test{
    public void printMatixClockWisely(int[][] array){
        if (array==null)
            return;
        int start =0 ;
        //只要还在矩阵范围内就循环打印,行和列长度;
        //start++ 来控制由外向里 每层减1
        while (array[0].length>start*2 && array.length>start*2){
            printOneCircle(array,start);
            start++;
        }
    }
    private void printOneCircle(int[][] array, int start) {

        // 打印目前环的上行,从左向右打印
        for (int i=start;i<array[0].length-start;i++){
            System.out.print(array[start][i]+" ");
        }
        // 打印目前环的右行,从上向下打印
        if (array.length-1-start>start){
            for (int i=start+1;i<array.length-start-1;i++){
                System.out.print(array[i][array[0].length-1-start]+" ");
            }
        }
        //打印目前环的下行,-1是数组下标计数从0开始
        if (array[0].length-1-start>start && array.length-1-start >start){
            for (int i=array[0].length-1-start;i>start;i--){
                System.out.print(array[array.length-start-1][i]+" ");
            }
        }
        //打印目前环的左行
        if (array.length-1-start > start && array[0].length-1-start >start){
            for (int i=array.length-start-1;i>start;i--){
                System.out.print(array[i][start]+" ");
            }
        }
    }
    public static void main(String[] args) {
        Test test = new Test();
        int[][] arr = {{1,2,3,0},{4,5,6,0},{7,8,9,0},{10,11,12,0}};
        test.printMatixClockWisely(arr);
        //输出结果为:1 2 3 0 0 0 0 12 11 10 7 4 5 6 9 8 
    }
}

你可能感兴趣的:(题目)