CodeTop快手高频算法题

450 阅读3分钟

1. leetcode206 反转链表

1.1 解题思路1:迭代

image.png

1.2 代码实现1😊

// 时间复杂度:O(N)
// 空间复杂度:O(1)
class Solution {
    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;
    }
}

1.3 解题思路2:递归

image.png

1.4 代码实现2😊

// 时间复杂度:O(N)
// 空间复杂度:O(N)
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return p;
    }
}

2. leetcode88合并两个有序数组

2.1 解题思路:逆向双指针

image.png image.png

2.2 代码实现😊

// 时间复杂度:O(m + n)
// 空间复杂度:O(1)
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m - 1;
        int j = n - 1;
        int k = m + n - 1;
        while (j >= 0) {
            if (i >= 0 && nums1[i] >= nums2[j]) {
                nums1[k--] = nums1[i--];
            } else {
                nums1[k--] = nums2[j--];
            }
        }
    }
}

3. leetcode3 无重复字符的最长子串

3.1 解题思路:滑动窗口

image.png image.png

3.2 代码实现😊

// 时间复杂度:O(N)
// 空间复杂度:O(∣Σ∣)
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> map = new HashMap<>();
        int ans = 0;
        for (int end = 0, start = 0; end < s.length(); end++) {
            char temp = s.charAt(end);
            if (map.containsKey(temp)) {
                // 防止start左移
                start = Math.max(start, map.get(temp) + 1);
            }
            ans = Math.max(ans, end - start + 1);
            map.put(temp, end);
        }
        return ans;
    }
}

4. 手撕快速排序

4.1 代码实现😊

// 时间复杂度:O(NlogN)
class Solution {
    public void quickSort(int[] nums, int low, int high) {
        if (low < high) {
            int pivotPos = partition(nums, low, high);
            quickSort(nums, low, pivotPos - 1);
            quickSort(nums, pivotPos + 1, high);
        }
    }

    private int partition(int[] nums, int low, int high) {
        int pivot = nums[low];
        while (low < high) {
            while (low < high && nums[high] >= pivot)
                --high;
            nums[low] = nums[high];
            while (low < high && nums[low] < pivot)
                ++low;
            nums[high] = nums[low];
        }
        nums[low] = pivot;
        return low;
    }
}

5. leetcode21 合并两个有序链表

5.1 解题思路1:迭代

image.png

5.2 代码实现😊

class Solution {
// 时间复杂度:O(m + n)
// 空间复杂度:O(1)
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1);
        ListNode point = dummy;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                point.next = l1;
                l1 = l1.next;
            } else {
                point.next = l2;
                l2 = l2.next;
            }
            point = point.next;
        }
        if (l1 != null)
            point.next = l1;
        if (l2 != null)
            point.next = l2;
        return dummy.next;
    }
}

5.3 解题思路2:递归

image.png

5.4 代码实现😊

class Solution {
// 时间复杂度:O(m + n)
// 空间复杂度:O(m + n)
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        } else if (l2 == null) {
            return l1;
        } else if (l1.val <= l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }
}

6. leetcode23 合并K个升序链表

6.1 解题思路1:顺序合并

image.png

6.2 代码实现

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0)
            return null;
        ListNode outputList = lists[0];
        for (int i = 1; i < lists.length; i++) {
            outputList = mergeTwoLists(outputList, lists[i]);
        }
        return outputList;
    }

    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        } else if (l2 == null) {
            return l1;
        } else if (l1.val <= l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }
}

6.3 解题思路2:分治解法

image.png

6.4 代码实现

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0)
            return null;
        return merge(lists, 0, lists.length - 1);
    }

    private ListNode merge(ListNode[] listNodes, int left, int right) {
        if (left == right)
            return listNodes[left];
        if (left > right)
            return null;
        int mid = left + (right - left) / 2;
        ListNode mergedLeft = merge(listNodes, left, mid);
        ListNode mergedRight = merge(listNodes, mid + 1, right);
        return mergeTwoLists(mergedLeft, mergedRight);
    }

    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        } else if (l2 == null) {
            return l1;
        } else if (l1.val <= l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }
}

6.5 解题思路3:优先队列

image.png

6.6 代码实现😊

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue<ListNode> priorityQueue =
                new PriorityQueue<>((o1, o2) -> o1.val - o2.val);
        for (int i = 0; i < lists.length; i++) {
            if (lists[i] == null)
                continue;
            priorityQueue.add(lists[i]);
        }
        ListNode dummy = new ListNode(-1);
        ListNode curr = dummy;
        while (!priorityQueue.isEmpty()) {
            ListNode minNode = priorityQueue.remove();
            curr.next = minNode;
            curr = curr.next;
            if (minNode.next != null) {
                priorityQueue.add(minNode.next);
            }
        }
        return dummy.next;
    }
}

7. leetcode53 最大子序和

7.1 代码实现😊:动态规划

class Solution {
    public int maxSubArray(int[] nums) {
        // 1. 状态定义:dp[i] 表示以索引为 i 的元素结尾的最大子数组之和
        int[] dp = new int[nums.length];
        // 2. 状态初始化
        dp[0] = nums[0];
        int maxSum = nums[0];
        // 3. 状态转移
        for (int i = 1; i < nums.length; i++) {
            dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
            maxSum = Math.max(maxSum, dp[i]);
        }
        // 4. 返回状态值
        return maxSum;
    }
}

8. leetcode102 二叉树的层序遍历

8.1 代码实现1:😊迭代

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null)
            return res;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> levelNodes = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                levelNodes.add(node.val);
                if (node.left != null)
                    queue.offer(node.left);
                if (node.right != null)
                    queue.offer(node.right);
            }
            res.add(levelNodes);
        }
        return res;
    }
}

8.2 代码实现2:😊递归

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null)
            return res;
        dfs(root, 0, res);
        return res;
    }

    private void dfs(TreeNode node, int currLevel, List<List<Integer>> res) {
        if (node == null)
            return;
        if (res.size() == currLevel) {
            List<Integer> levelNodes = new ArrayList<>();
            levelNodes.add(node.val);
            res.add(levelNodes);
        } else {
            res.get(currLevel).add(node.val);
        }
        dfs(node.left, currLevel + 1, res);
        dfs(node.right, currLevel + 1, res);
    }
}

9. leetcode146 LRU缓存机制

9.1 代码实现😊

class LRUCache {
    class DListNode {
        int key;
        int value;
        DListNode prev;
        DListNode next;

        public DListNode() {

        }

        public DListNode(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    Map<Integer, DListNode> cache = new HashMap<>();
    int capacity;
    DListNode head;
    DListNode tail;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        head = new DListNode();
        tail = new DListNode();
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        DListNode node = cache.get(key);
        if (node == null) {
            return -1;
        } else {
            moveNodeToHead(node);
            return node.value;
        }

    }

    public void put(int key, int value) {
        DListNode node = cache.get(key);
        if (node == null) {
            if (cache.size() == capacity) {
                DListNode delNode = removeTailNode();
                cache.remove(delNode.key);
            }
            DListNode newNode = new DListNode(key, value);
            cache.put(key, newNode);
            addNodeToHead(newNode);
        } else {
            node.value = value;
            moveNodeToHead(node);
        }
    }

    private void moveNodeToHead(DListNode node) {
        removeNode(node);
        addNodeToHead(node);
    }

    private void addNodeToHead(DListNode node) {
        node.next = head.next;
        node.next.prev = node;
        node.prev = head;
        head.next = node;
    }

    private void removeNode(DListNode node) {
        DListNode preNode = node.prev;
        DListNode nextNode = node.next;
        preNode.next = nextNode;
        nextNode.prev = preNode;
        node.prev = null;
        node.next = null;
    }

    private DListNode removeTailNode() {
        DListNode delNode = tail.prev;
        removeNode(delNode);
        return delNode;
    }
}

10. leetcode144 二叉树的前序遍历

10.1 代码实现1:😊递归

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preOrder(root, res);
        return res;
    }

    private void preOrder(TreeNode node, List<Integer> res) {
        if (node == null)
            return;
        res.add(node.val);
        preOrder(node.left, res);
        preOrder(node.right, res);
    }
}

10.2 代码实现2:😊迭代

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null)
            return res;
        Deque<TreeNode> stack = new ArrayDeque<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            res.add(node.val);
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        return res;
    }
}

11. leetcode46 全排列

11.1 代码实现😊

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<Integer> path = new ArrayList<>();
        List<List<Integer>> res = new ArrayList<>();
        boolean[] used = new boolean[nums.length];
        backtrack(nums, path, res, used);
        return res;
    }

    private void backtrack(int[] nums,
                           List<Integer> path,
                           List<List<Integer>> res,
                           boolean[] used) {
        if (path.size() == nums.length) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i])
                continue;
            path.add(nums[i]);
            used[i] = true;
            backtrack(nums, path, res, used);
            path.remove(path.size() - 1);
            used[i] = false;
        }
    }
}

12. leetcode47 全排列II

12.1 代码实现😊

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<Integer> path = new ArrayList<>();
        List<List<Integer>> res = new ArrayList<>();
        boolean[] used = new boolean[nums.length];
        Arrays.sort(nums);
        backtrack(nums, path, res, used);
        return res;
    }

    private void backtrack(int[] nums,
                           List<Integer> path,
                           List<List<Integer>> res,
                           boolean[] used) {
        if (path.size() == nums.length) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i])
                continue;
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) 
                continue;
            path.add(nums[i]);
            used[i] = true;
            backtrack(nums, path, res, used);
            path.remove(path.size() - 1);
            used[i] = false;
        }
    }
}

13. leetcode141 环形链表

13.1 代码实现:😊快慢指针

// 时间复杂度:O(N)
// 空间复杂度:O(1)
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast)
                return true;
        }
        return false;
    }
}

14. leetcode142 环形链表 II

14.1 代码实现:😊快慢指针

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                fast = head;
                while (slow != fast) {
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow;
            }
        }
        return null;
    }
}

15. leetcode160 相交链表

15.1 代码实现😊

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null)
            return null;
        ListNode pA = headA;
        ListNode pB = headB;
        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pA;
    }
}

16. leetcode215 数组中的第K个最大元素

16.1 解题思路1:堆排序

image.png

16.2 代码实现1:😊堆排序

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int n = nums.length;
        PriorityQueue<Integer> priorityQueue;
        int capacity;
        if (k < n - k) {
            // k比较小,构建小顶堆,寻找第 K 个最大元素
            capacity = k;
            priorityQueue = new PriorityQueue<>(capacity + 1);
        } else {
            // k比较大,构建大顶堆,寻找第 N - K + 1 个最小元素
            capacity = n - k + 1;
            priorityQueue =
                    new PriorityQueue<>(capacity + 1, ((o1, o2) -> o2 - o1));
        }
        for (int i = 0; i < nums.length; i++) {
            priorityQueue.add(nums[i]);
            if (priorityQueue.size() > capacity) {
                priorityQueue.remove();
            }
        }
        return priorityQueue.peek();
    }

}

16.3 代码实现2:😊快排

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return quickSelect(nums, 0, nums.length - 1, nums.length - k);
    }

    private int quickSelect(int[] nums, int low, int high, int target) {
        while (true) {
            int index = partition(nums, low, high);
            if (index == target) {
                return nums[index];
            } else if (index < target) {
                low = index + 1;
            } else {
                high = index - 1;
            }
        }
    }

    private int partition(int[] nums, int low, int high) {
        int pivot = nums[low];
        while (low < high) {
            while (low < high && nums[high] >= pivot) {
                high--;
            }
            nums[low] = nums[high];
            while (low < high && nums[low] < pivot) {
                low++;
            }
            nums[high] = nums[low];
        }
        nums[low] = pivot;
        return low;
    }
}

17. leetcode92 反转链表II

17.1 解题思路:头插法

image.png

17.2 代码实现😊

// 时间复杂度:O(N)
// 空间复杂度:O(1)
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode prev = dummy;
        for (int i = 0; i < left - 1; i++) {
            prev = prev.next;
        }
        ListNode curr = prev.next;
        for (int i = 0; i < right - left; i++) {
            ListNode next = curr.next;
            curr.next = next.next;
            next.next = prev.next;
            prev.next = next;
        }
        return dummy.next;
    }
}

18. leetcode103 二叉树的锯齿形层序遍历

18.1 代码实现😊

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Deque<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int level = 1;
        while (!queue.isEmpty()) {
            int size = queue.size();
            LinkedList<Integer> levelNodes = new LinkedList<>();
            boolean isLeftToRight = level % 2 == 1 ? true : false;
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                if (isLeftToRight) {
                    levelNodes.addLast(node.val);
                } else {
                    levelNodes.addFirst(node.val);
                }
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            res.add(new LinkedList<>(levelNodes));
            level++;
        }
        return res;
    }
}

19. leetcode415 字符串相加

19.1 代码实现😊

class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder res = new StringBuilder();
        int i = num1.length() - 1;
        int j = num2.length() - 1;
        int carry = 0;
        while (i >= 0 || j >= 0) {
            int n1 = i >= 0 ? num1.charAt(i) - '0' : 0;
            int n2 = j >= 0 ? num2.charAt(j) - '0' : 0;
            int temp = n1 + n2 + carry;
            carry = temp / 10;
            res.append(temp % 10);
            i--;
            j--;
        }
        if (carry == 1)
            res.append(1);
        return res.reverse().toString();
    }
}

20 leetcode20 有效的括号

20.1 代码实现😊

class Solution {
    public boolean isValid(String s) {
        Deque<Character> stack = new ArrayDeque<>();
        for (char c : s.toCharArray()) {
            if (c == '(')
                stack.push(')');
            if (c == '[')
                stack.push(']');
            if (c == '{')
                stack.push('}');
            if (c == ')' || c == ']' || c == '}') {
                if (stack.isEmpty() || c != stack.pop())
                    return false;
            }
        }
        return stack.isEmpty();
    }
}