常见算法

117 阅读2分钟

链接相关

反转链表

//迭代法

public ListNode reverseList(ListNode head) {

        ListNode prev = null;

        ListNode curr = head;

        while (curr != null) {

            ListNode next = curr.next;

            curr.next = prev;

            prev = curr;

            curr = next;

        }

        return prev;

    }

//递归

public ListNode reverseList(ListNode head) {

        if (head == null || head.next == null) {

            return head;

        }

        ListNode newHead = reverseList(head.next);

        head.next.next = head;

        head.next = null;

        return newHead;

    }

链表中是否有环

//快慢指针

 public boolean hasCycle(ListNode head) {

        if (head == null || head.next == null) {

            return false;

        }

        ListNode slow = head;

        ListNode fast = head.next;

        while (slow != fast) {

            if (fast == null || fast.next == null) {

                return false;

            }

            slow = slow.next;

            fast = fast.next.next;

        }

        return true;

    }

链表是否相交,相交返回改结点否则返回null

 public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        if (headA == null || headB == null) {

            return null;

        }

        ListNode pA = headA, pB = headB;

        while (pA != pB) {

            pA = pA == null ? headB : pA.next;

            pB = pB == null ? headA : pB.next;

        }

        return pA;

    }

链表的中间结点

思路:快指针q每次走2步,慢指针p每次走1步,当q走到末尾时p正好走到中间。

    ListNode* middleNode(ListNode* head) {

        ListNode* slow = head;

        ListNode* fast = head;

        while (fast != NULL && fast->next != NULL) {

            slow = slow->next;

            fast = fast->next->next;

        }

        return slow;

    }

X的平方根

//二分查找

int mySqrt(int x) 

    {

        if(x == 1)

            return 1;

        int min = 0;

        int max = x;

        while(max-min>1)

        {

            int m = (max+min)/2;

            if(x/m<m)

                max = m;

            else

                min = m;

        }

        return min;

    }

\

二叉树

二叉树遍历

判断一棵树是否是二叉搜索树 

//中序遍历的方法实现

bool isBST(TreeNode *root)

{

    static TreeNode *prev;

    if(root != NULL)

    {

        if(!isBST(root->left))

            return false;

        if(prev != NULL && root->data < prev->data)

            return false;

        prev = root;

        if(!isBST(root->right))

            return false;

    }

    return true;

}

\

\

二叉树的最大深度

方法一:深度优先搜索

int maxDepth(TreeNode* root) {

        if (root == NULL) return 0;

        return max(maxDepth(root->left), maxDepth(root->right)) + 1;

    }

复杂度分析

时间复杂度:O(n)O(n),其中 nn 为二叉树节点的个数。每个节点在递归中只被遍历一次。

空间复杂度:O(\textit{height})O(height),其中 \textit{height}height 表示二叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于二叉树的高度。

是否平衡二叉树

平衡二叉树的定义是:二叉树的每个节点的左右子树的高度差的绝对值不超过 11,则二叉树是平衡二叉树。根据定义,一棵二叉树是平衡二叉树,当且仅当其所有子树也都是平衡二叉树

public boolean isBalanced(TreeNode root) {

        if (root == null) {

            return true;

        } else {

            return Math.abs(height(root.left) - height(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);

        }

    }

    public int height(TreeNode root) {

        if (root == null) {

            return 0;

        } else {

            return Math.max(height(root.left), height(root.right)) + 1;

        }

    }

时间复杂度:on2

空间复杂度:O(n)

动态规划

爬楼梯(腾讯)

f(x)=f(x−1)+f(x−2)

方法一 :动态规划  时间复杂度o(n)  空间复杂度o(1)

int climbStairs(int n) {

        int p = 0, q = 0, r = 1;

        for (int i = 1; i <= n; ++i) {

            p = q; 

            q = r; 

            r = p + q;

        }

        return r;

    }

\

方法二:通项公式

 public int climbStairs(int n) {

        double sqrt5 = Math.sqrt(5);

        double fibn = Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1);

        return (int) Math.round(fibn / sqrt5);

    }