剑指offer(java版)面试题14-——面试题24

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Katrina_ALi/article/details/81192866

面试题14:数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

    代码:(有点乱,可以整理的更清晰)
            public class Solution {
                public double Power(double base, int exponent) {
                    if(exponent==0) return 1.0;//0的0次方按照1来算
                    if(base == 0.0) {
                        if(exponent>0) {
                            return 0.0;
                        }else {
                            throw new RuntimeException("分母不能为0"); //分母为0的时候,要抛异常!
                        }
                    }

                    double s = 1;
                    if(exponent>0){ //指数为正的时候
                        for(int i=0;i<exponent;i++) {
                            s = s*base; 
                        }
                    }else { //指数为负的时候
                        for(int i=0;i<-exponent;i++) {
                            s = s/base;
                        }
                    }      
                    return s;      
              }
            }

需要注意的点:
(1)java中作为基本数据类型的浮点数只有float和double。double是8字节,64位。
(2)如果开发者需要精确保存一个浮点数,则可以考虑使用BigDecimal类。
(3)int整数需要考虑负数、0、整数!,底数也需要考虑是否为0.同时,幂的运算要考虑正负数计算是不同的!

面试题15:调整数组顺序使奇数位于偶数前面

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

代码:(另外开辟了数组用来空间换时间,可以减少算法的复杂度)
            public class Solution {
                public void reOrderArray(int [] array) {
                    if(array == null) return;
                    int n = array.length;
                    int [] a;
                    a = new int [n];
                    int odd=0;//用来记录奇数的个数
                    for(int i=0;i<n;i++) {
                        if(array[i]%2 != 0) {
                            odd+=1;
                        }
                    }
                    if(odd==0 || odd==n) return;
                    int first=0,second=odd;
                    for(int i=0;i<n;i++) {
                        if(array[i]%2==0) {
                            a[second]=array[i];
                            second++;
                        }else {
                            a[first]=array[i];
                            first++;
                        }
                    }
                    for(int i=0;i<n;i++) {
                        array[i] = a[i];
                    }
                }
            }

面试题16:链表中倒数第k个结点

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

注意:
头结点的数据域可以不存储任何信息,头结点的指针域存储指向第一个结点的指针(即第一个元素结点的存储位置)

方法一:定义快指针和慢

方法二:先求长度再去计算位置

            public ListNode FindKthToTail(ListNode head,int k) {
                    //这个head就是链表的第一个节点!!
                        if(head == null) return null;
                        ListNode p = head;
                        int num=0;
                        while(p != null) {
                            p = p.next;
                            num++;
                        }
                        p = head;
                        if(num<k) {
                            return null;
                        }else {
                            for(int i=0;i<num-k;i++) {
                                p = p.next;
                            }
                            return p;
                        }

                }

注意:牛客上面给出的头结点就是链表的第一个节点,而不是常规意义上的头结点!!切记!不然代码会错!

面试题17:反转链表

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

        代码:
            public class Solution {
                public ListNode ReverseList(ListNode head) {
                    if(head == null) return null;
                    //if(head.next==null) return head;
                    ListNode former = null;
                    ListNode latter = null;
                    while(head != null) {
                        former = head.next;
                        head.next = latter;
                        latter = head;
                        head = former;
                    }
                    return latter;
                }
            }

面试题18:合并两个排序的链表

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

代码:(非递归版本)
            public class Solution {
                public ListNode Merge(ListNode list1,ListNode list2) {
                    if(list1 == null) return list2;
                    if(list2 == null) return list1;
                    ListNode head,current;
                    if(list1.val<list2.val) {
                        head = list1;
                        list1 = list1.next;
                    }else {
                        head = list2;
                        list2 = list2.next;
                    }
                    current = head;

                    while(list1 != null && list2 != null) {
                        if(list1.val < list2.val) {
                            current.next = list1;
                            list1 = list1.next;
                        }else {
                            current.next = list2;
                            list2 = list2.next;
                        }
                        current = current.next;
                    }
                    if(list1 != null) {
                        current.next=list1;
                    }else {
                        current.next = list2;
                    }
                    return head;
                }
            }

代码:(递归版本)

注意:两个链表的合并可以新建一个第三方链表来存储,这样减少了工作量!

面试题19:树的子结构

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

面试题20:二叉树的镜像

操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:

二叉树的镜像定义:源二叉树 
        8
       /  \
      6   10
     / \  / \
    5  7 9 11
    镜像二叉树
        8
       /  \
      10   6
     / \  / \
    11 9 7  5

代码:

        public class Solution {
            public void Mirror(TreeNode root) {
                if(root == null) return;
                TreeNode m = null;
                m = root.left;
                root.left = root.right;
                root.right = m;
                Mirror(root.left);
                Mirror(root.right);
                return;
            }
        }

注意:
这到期主要考察的就是二叉树的知识

面试题21:顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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.

代码:

面试题22:包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

代码:
            import java.util.Stack;
            public class Solution {
                Stack<Integer> s1 = new Stack<Integer>(); 
                Stack<Integer> s2 = new Stack<Integer>(); 

                public void push(int node) {
                    s1.push(node);
                    if(s2.isEmpty()) {          
                        s2.push(node);
                    }else if(s2.peek()<=node) {
                        s2.push(s2.peek());
                    }else {
                        s2.push(node);
                    }
                }

                public void pop() {
                    s1.pop();
                    s2.pop();//同步弹出
                }

                public int top() {
                    return s1.peek();
                }

                public int min() {
                   return  s2.peek();
                }

            }

注意:

public peek() 查看栈顶对象而不移除它
2.使用的思路是用辅助栈来同步保存最小值!

面试题23:栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

代码1:(以push为外循环)
        import java.util.ArrayList;
        import java.util.Stack;
        public class Solution {
            public boolean IsPopOrder(int [] pushA,int [] popA) {
                 if(pushA.length==0 || popA.length==0) return false;
                 Stack<Integer> s = new Stack<Integer> ();
                 int i = 0;
                 for(int a : pushA) {
                     s.push(a);
                     while(!s.isEmpty() && s.peek()==popA[i] ) {
                         s.pop();
                         i++;
                     }
                 }
                 return s.isEmpty()?true:false;
            }
        }
代码二:(以pop为外循环)  

思路:(这道题需要找规律)

借助辅助栈,如果当前的栈顶是要出栈的元素,那么直接弹出,如果不是,那么将后续需要入栈的元素压入,知道找到出栈元素,如果全都压入了还没找到,那么说明序列不可能是弹出序列!
这道题如果不借助辅助栈的话可能会非常麻烦,而借助辅助栈的话可以同步模拟压入的过程,查看是否是序列,这样问题就好解决了!

面试题24:从上往下打印二叉树

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

代码:
        import java.util.ArrayList;
        public class Solution {
            public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
                ArrayList<Integer> a=new ArrayList<Integer>();
                ArrayList<TreeNode> list=new ArrayList<TreeNode>();
                if(root==null)  return a;     
                list.add(root);
                while(list.size() != 0) {
            //注意:这里写list!=null是错的,因为list是存在的,只不过大小是0而已!
                    TreeNode p = list.remove(0);
                    a.add(p.val);
                    if(p.left != null) {
                        list.add(p.left);
                    }
                    if(p.right != null) {
                        list.add(p.right);
                    }
                }
                return a;
            }
        }

思路:不要把这种遍历看成是层与层之间的,而要看成是一个连着的!借助队列来实现
注意:
<1>队列:使用的也是ArrayList来模拟队列的实现,这个和Stack貌似不太一样。
<2>注意上面注释那里,这是小点可能会疏忽!
<3>这道题考察的是树和树的遍历算法,但是没有用到递归,而是结合了队列的数据结构,所以当问题超出常理的时候要尽量去思考能否用别的思维来解释,以及灵活结合其他的数据结构,比如:队列、栈、哈希表等!

猜你喜欢

转载自blog.csdn.net/Katrina_ALi/article/details/81192866