LeetCode 剑指 Offer 刷题代码 (2)

面试题31. 栈的压入、弹出序列

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

    public static boolean validateStackSequences(int[] pushed, int[] popped) {
        if(pushed==null || pushed.length==0)
            return true;
        Stack<Integer> stack = new Stack<Integer>();
        int indexPop = 0;

        for (int i=0; i<pushed.length; i++){
            stack.add(pushed[i]);
            while( indexPop<popped.length && !stack.isEmpty() && stack.peek()==popped[indexPop]){
                indexPop++;
                stack.pop();
            }
        }

        return stack.isEmpty();
    }

面试题30. 包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

    class MinStack {

        class Node{
            int val, curMinValue;

            public Node(int val, int curMinValue) {
                this.val = val;
                this.curMinValue = curMinValue;
            }
        }

        private Stack<Node> stack = new Stack();

        /** initialize your data structure here. */
        public MinStack() {

        }

        public void push(int x) {
            if(stack.isEmpty()){
                stack.add(new Node(x,x));
            }else {
                int curMinValue = x<stack.peek().curMinValue?x:stack.peek().curMinValue;
                stack.add(new Node(x,curMinValue));
            }
        }

        public void pop() {
            stack.pop();
        }

        public int top() {
            return stack.peek().val;
        }

        public int min() {
            return stack.peek().curMinValue;
        }
    }

面试题29. 顺时针打印矩阵

    public int[] spiralOrder(int[][] matrix) {
        if(matrix==null || matrix.length==0 || matrix[0].length==0)
            return new int[0];
        int l=0, r=matrix[0].length-1, u=0, d=matrix.length-1;
        int [] res = new int[(r+1)*(d+1)];
        int k=0;
        while (true){
            for (int i=l; i<=r; i++) res[k++]=matrix[u][i];
            if(++u>d) break;

            for(int i=u; i<=d; i++) res[k++]=matrix[i][r];
            if(l>--r) break;

            for (int i=r; i>=l; i--) res[k++] = matrix[d][i];
            if(u>--d) break;

            for(int i=d; i>=u; i--) res[k++] = matrix[i][l];
            if(++l>r) break;
        }
        return res;
    }

面试题28. 对称的二叉树

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

    public boolean isSymmetric(TreeNode root) {
        if(root==null)
            return true;
        return compare(root.left,root.right);
    }

    private boolean compare(TreeNode left, TreeNode right) {
        if(left==null && right==null)
            return true;
        if(left==null || right==null || left.val!=right.val)
            return false;
        return compare(left.left,right.right) && compare(left.right,right.left);
    }

面试题27. 二叉树的镜像

请完成一个函数,输入一个二叉树,该函数输出它的镜像。

    public TreeNode mirrorTree(TreeNode root) {
        if(root == null)
            return root;
        TreeNode t = root.left;
        root.left = root.right;
        root.right = t;

        mirrorTree(root.left);
        mirrorTree(root.right);
        return root;
    }

面试题26. 树的子结构

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

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if (A == null || B == null)
            return false;
        return isSub(A, B) || isSubStructure(A.left,B)|| isSubStructure(A.right,B);
    }
    

    public boolean isSub(TreeNode A, TreeNode B) {
        if (B == null)
            return true;
        if (A == null || A.val != B.val)
            return false;

        if (isSub(A.left, B.left) && isSub(A.right, B.right))
            return true;
        return false;
    }

面试题25. 合并两个排序的链表

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(0), tmp, pre;
        head.next = null; pre = head;

        while(l1!=null && l2!=null){
            if(l1.val<l2.val){
                pre.next = l1;
                l1 = l1.next;
            }else {
                pre.next = l2;
                l2 = l2.next;
            }
            pre = pre.next;
        }
        if(l1!=null)
            pre.next=l1;
        if(l2!=null)
            pre.next=l2;

        return head.next;
    }

面试题24. 反转链表

    public ListNode reverseList(ListNode head) {
        if(head==null)
            return null;
        ListNode tmp = new ListNode(head.val), res=null;
        tmp.next = null;
        head = head.next;
        while (head!=null){
            res = new ListNode(head.val);
            res.next = tmp;
            tmp = res;
            head = head.next;
        }
        return res;
    }

面试题22. 链表中倒数第k个节点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。

    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode res = head, tmp = head;
        int ant = 0;
        while(ant++<k) tmp=tmp.next;
        while (tmp!=null){
            tmp = tmp.next;
            res = res.next;
        }
        return res;
    }

面试题21. 调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

    public int[] exchange(int[] nums) {
        if(nums==null || nums.length==0)
            return new int[0];
        int i=0, j=nums.length-1;

        while(i!=j){
            while (i!=j && nums[j]%2==0)
                j--;
            while (i!=j && nums[i]%2==1)
                i++;
            int t=nums[i];nums[i]=nums[j];nums[j]=t;
        }
        return nums;
    }

面试题18. 删除链表的节点

public ListNode deleteNode(ListNode head, int val) {
        if(head == null)
            return null;
        if(head.val == val)
            return head.next;

        ListNode tmp = head;
        while (tmp.next != null && tmp.next.val!=val){
            tmp = tmp.next;
        }

        if(tmp.next!=null)
            tmp.next = tmp.next.next;

        return head;
    }

面试题16. 数值的整数次方

实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。

    /*
    n为偶数,pow(8)=pow(4)*pow(4),pow(4)=pow(2)*pow(2),pow(2)=pow(1)*pow(1)
    n为奇数,pow(9)=pow(4)*pow(4)*base,pow(4)=pow(2)*pow(2),pow(2)=pow(1)*pow(1)
     */
    public double myPow(double x, int n) {
        int flag = 1;
        if(n<0){
            flag = 0;
            n = -n;
        }
        double ans = myPowLgc(x,n);

        if(flag==0)
            return 1/ans;
        else
            return ans;
    }
    public double myPowLgc(double x, int n){
        if (n == 0)
            return 1;
        if(n==1)
            return x;
        double ans = myPowLgc(x,n/2);
        if(n%2==0)
            return ans*ans;
        else
            return ans*ans*x;
    }

面试题15. 二进制中1的个数

请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。

    public int hammingWeight(int n) {
        int count = 0;
        while(n!=0){
            count += n&1;
            n = n>>>1;
        }
        return count;
    }

面试题14- I. 剪绳子

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m] 。请问 k[0]k[1]…*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

    public int cuttingRope(int n) {
        int res = -1;
        for(int m=2; m<=n; m++){
            res = Math.max(res, getMax(n,m));
        }
        return res;
    }

    private int getMax(int n, int m) {
        int res = 1;
        int a = n/m, b=n%m;
        for(int i=0; i<m; i++)
            if(b-->0)
                res = res * (a+1);
            else
                res = res * a;
        return res;
    }

你可能感兴趣的:(LeetCode 剑指 Offer 刷题代码 (2))