[LeetCode] 热题100

发布时间 2023-12-22 16:56:43作者: Vivid-BinGo

128 最长连续序列

public class Solution
{
    public int longestConsecutive(int[] nums)
    {
        if (nums == null || nums.length == 0) return 0;
        int ans = 1;
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums)
        {
            if (map.containsKey(num)) continue;
            map.put(num, 1);
            if (map.containsKey(num - 1))
                ans = Math.max(ans, merge(map, num - 1, num));
            if (map.containsKey(num + 1))
                ans = Math.max(ans, merge(map, num, num + 1));
        }
        return ans;
    }

    private int merge(HashMap<Integer, Integer> map, int less, int more)
    {
        int r = more + map.get(more) - 1;
        int l = less - map.get(less) + 1;
        int len = r - l + 1;
        map.put(r, len);
        map.put(l, len);
        return len;
    }
}

15 三数之和

class Solution {

	public static List<List<Integer>> threeSum(int[] nums)
	{
		List<List<Integer>> ans = new ArrayList<List<Integer>>();
		Arrays.sort(nums);
		List<int[]> res;
		for (int i = 0; i < nums.length; i++)
		{
			res = twoSum(nums, i + 1, -nums[i]);
			if (res.size() != 0)
			{
				for (int[] t : res)
				{
					List<Integer> temp = new ArrayList<Integer>();
					for (int k = 0; k < t.length; k++)
						temp.add(t[k]);
					ans.add(temp);
				}
			}
			while (i < nums.length - 1 && nums[i] == nums[i + 1])
				i++;

		}
		return ans;
	}

	public static List<int[]> twoSum(int[] nums, int s, int target)
	{
		List<int[]> ans = new ArrayList<int[]>();
		int l = s, r = nums.length - 1, left = -1, right = -1;
		while (l < r)
		{
			if (nums[l] + nums[r] > target)
				r--;
			else if (nums[l] + nums[r] < target)
				l++;
			else
			{
				left = nums[l];
				right = nums[r];
				ans.add(new int[]
				{ nums[s - 1], left, right });
				while (l < r && nums[l] == left)
					l++;
				while (l < r && nums[r] == right)
					r--;
			}
		}
		return ans;
	}
}

560 和为 K 的子数组

public class Solution
{
    public int subarraySum(int[] nums, int k)
    {
        HashMap<Integer, Integer> map = new HashMap<>();
        int pre = 0, ans = 0;
        map.put(0, 1);
        for (int num : nums)
        {
            pre += num;
            if (map.containsKey(pre - k))
                ans += map.get(pre - k);
            map.put(pre, map.getOrDefault(pre, 0) + 1);
        }
        return ans;
    }
}

239 滑动窗口最大值

public class Solution
{
    public int[] maxSlidingWindow(int[] nums, int k)
    {
        Deque<Integer> que = new LinkedList<>();
        int[] ans = new int[nums.length - k + 1];
        for (int i = 0; i < nums.length; i++)
        {
            while (!que.isEmpty() && nums[i] >= nums[que.getLast()])
                que.pollLast();
            que.addLast(i);
            if (i - que.getFirst() + 1 > k)
                que.pollFirst();
            if (i >= k - 1)
                ans[i - k + 1] = nums[que.getFirst()];
        }
        return ans;
    }
}

41 缺失的第一个正数

public class Solution
{
    public int firstMissingPositive(int[] nums)
    {
        int l = 0, r = nums.length;
        while (l < r)
        {
            if (l + 1 == nums[l])
                l++;
            else if (nums[l] <= l || nums[l] > r || nums[nums[l] - 1] == nums[l])
                nums[l] = nums[--r];
            else
                swap(nums, l, nums[l] - 1);
        }
        return l + 1;
    }

    private void swap(int[] nums, int i, int j)
    {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

2276 统计区间中的整数数目

class CountIntervals
{

    int curL, curR, cnt;
    public CountIntervals left, right;

    public CountIntervals()
    {
        curL = 1;
        curR = (int) 1E9;
    }

    public CountIntervals(int l, int r)
    {
        curL = l;
        curR = r;
    }

    public void add(int l, int r)
    {
        if (cnt == curR - curL  + 1) return;
        if (l <= curL && curR <= r)
        {
            cnt = curR - curL + 1;
            return;
        }
        int mid = (curL + curR) / 2;
        if (left == null) left = new CountIntervals(curL, mid);
        if (right == null) right = new CountIntervals(mid + 1, curR);
        if (l <= mid) left.add(l, r);
        if (mid < r) right.add(l, r);
        cnt = left.cnt + right.cnt;
    }

    public int count()
    {
        return cnt;
    }
}

148 排序链表

public class Solution
{
    public ListNode sortList(ListNode head)
    {
        return sortList(head, null);
    }

    public ListNode sortList(ListNode head, ListNode tail)
    {
        if (head == null) return null;
        if (head.next == tail)
        {
            head.next = null;
            return head;
        }
        ListNode f = head, s = head;
        while (f != tail)
        {
            s = s.next;
            f = f.next;
            if (f != tail)
                f = f.next;
        }
        ListNode l = sortList(head, s);
        ListNode r = sortList(s, tail);
        return merge(l, r);
    }

    private ListNode merge(ListNode h1, ListNode h2)
    {
        ListNode l = h1, r = h2, dummyHead = new ListNode(0), temp = dummyHead;
        while (l != null && r != null)
        {
            if (l.val < r.val)
            {
                temp.next = l;
                l = l.next;
            }
            else
            {
                temp.next = r;
                r = r.next;
            }
            temp = temp.next;
            temp.next = null;
        }
        if (l != null)
            temp.next = l;
        if (r != null)
            temp.next = r;
        return dummyHead.next;
    }
}

98 验证二叉搜索树

class Solution {
    boolean isValidBST(TreeNode root)
    {
        return isValidBST(root, null, null);
    }

    boolean isValidBST(TreeNode root, TreeNode min, TreeNode max)
    {
        if (root == null) return true;
        if (min != null && root.val <= min.val) return false;
        if (max != null && root.val >= max.val) return false;
        return isValidBST(root.left, min, root) && isValidBST(root.right, root, max);
    }
}

22 括号生成

public class Solution
{
    List<String> res = new LinkedList<>();

    public List<String> generateParenthesis(int n)
    {
        StringBuilder str = new StringBuilder();
        dfs(n, n, str);
        return res;
    }

    public void dfs(int left, int right, StringBuilder str)
    {
        if (left > right) return;
        if (left + right == 0)
        {
            res.add(new String(str));
            return;
        }
        if (left > 0)
        {
            str.append('(');
            dfs(left - 1, right, str);
            str.deleteCharAt(str.length() - 1);
        }

        if (right > 0)
        {
            str.append(')');
            dfs(left, right - 1, str);
            str.deleteCharAt(str.length() - 1);
        }
    }
}

75 颜色分类

public class Solution
{
    public void sortColors(int[] nums)
    {
        int idx = 0, l = -1, r = nums.length;
        while (idx < r)
        {
            if (nums[idx] == 0)
                swap(nums, ++l, idx++);
            else if (nums[idx] == 2)
                swap(nums, --r, idx);
            else
                idx++;
        }
    }

    private void swap(int[] nums, int i, int j)
    {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

31 下一个排列

/*
 * 1.首先从后向前查找第一个顺序对, 满足 a[i]<a[i+1]
 * 2.如果找到了顺序对, 在区间 [i+1,n)中从后向前查找第一个元素 j 满足 a[i]<a[j]
 * 3.交换a[i]与a[j], 反转区间 [i+1,n)
 */
public class Solution
{
    public void nextPermutation(int[] nums)
    {
        int i, j;
        for (i = nums.length - 2; i >= 0; i--)
            if (nums[i] < nums[i + 1])
                break;
        if (i != -1)
        {
            for (j = nums.length - 1; j >= i + 1; j--)
                if (nums[j] > nums[i])
                    break;
            swap(nums, i, j);
        }
        reverse(nums, i + 1, nums.length - 1);
    }

    private void reverse(int[] nums, int l, int r)
    {
        while (l <= r)
        {
            swap(nums, l, r);
            l++;
            r--;
        }
    }

    private void swap(int[] nums, int i, int j)
    {
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }
}

287 寻找重复数

public class Solution
{
    public int findDuplicate(int[] nums)
    {
        int s = 0, f = 0;
        do
        {
            s = nums[s];
            f = nums[nums[f]];
        }
        while (s != f);
        s = 0;
        do
        {
            s = nums[s];
            f = nums[f];
        }
        while (s != f);
        return s;
    }
}

public class Solution
{
    public int findDuplicate(int[] nums)
    {
        int l = 1, r = nums.length - 1;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            int cnt = 0;
            for (int num : nums)
            {
                if (num <= mid)
                    cnt++;
            }
            if (cnt <= mid)
                l = mid + 1;
            else
                r = mid - 1;
        }
        return l;
    }
}

84 柱状图中最大的矩形

public class Solution
{
    public int largestRectangleArea(int[] heights)
    {
        int[] left = new int[heights.length];
        int[] right = new int[heights.length];
        int ans = -1;
        Arrays.fill(right, heights.length);
        Stack<Integer> incStack = new Stack<>();
        for (int i = 0; i < heights.length; i++)
        {
            while (!incStack.isEmpty() && heights[i] < heights[incStack.peek()])
            {
                right[incStack.peek()] = i;
                incStack.pop();
            }
            left[i] = incStack.isEmpty() ? -1 : incStack.peek();
            incStack.add(i);
        }
        for (int i = 0; i < heights.length; i++)
            ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
        return ans;
    }
}

215 数组中的第K个最大元素

public class Solution
{
    public int findKthLargest(int[] nums, int k)
    {
        int len = nums.length - 1;
        for (int i = nums.length / 2 - 1; i >= 0; i--)
            adjust(nums, i, len);
        while (--k > 0)
        {
            swap(nums, 0, len--);
            adjust(nums, 0, len);
        }
        return nums[0];
    }

    private void swap(int[] nums, int i, int j)
    {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    private void adjust(int[] nums, int idx, int n)
    {
        int temp = nums[idx], t = idx;
        while (idx <= n)
        {
            if (idx * 2 + 2 <= n && nums[idx * 2 + 1] < nums[idx * 2 + 2])
                idx = idx * 2 + 2;
            else
                idx = idx * 2 + 1;
            if (idx <= n && nums[idx] > temp)
            {
                swap(nums, idx, t);
                t = idx;
            }
            else break;
        }
    }
}

32 最长有效括号

public class Solution
{
    public int longestValidParentheses(String s)
    {
        //以s[i]结尾的最长有效长度
        int len = s.length(), ans = 0;
        int[] dp = new int[len];
        for (int i = 1; i < len; i++)
        {
            if (s.charAt(i) == '(') continue;
            int j = i - dp[i - 1] - 1;
            if (j >= 0 && s.charAt(i) != s.charAt(j))
                dp[i] = dp[i - 1] + 2 + (j - 1 >= 0 ? dp[j - 1] : 0);
            ans = Math.max(ans, dp[i]);
        }
        return ans;
    }
}

72 编辑距离

public class Solution
{
    public int minDistance(String word1, String word2)
    {
        if (word1.length() == 0) return word2.length();
        if (word2.length() == 0) return word1.length();
        int[][] dp = new int[word1.length()][word2.length()];
        for (int i = 0; i < word1.length(); i++)
            dp[i][0] = word1.substring(0, i + 1).indexOf(word2.charAt(0)) != -1 ? i : i + 1;
        for (int i = 0; i < word2.length(); i++)
            dp[0][i] = word2.substring(0, i + 1).indexOf(word1.charAt(0)) != -1 ? i : i + 1;
        for (int i = 1; i < word1.length(); i++)
        {
            for (int j = 1; j < word2.length(); j++)
            {
                if (word1.charAt(i) == word2.charAt(j))
                    dp[i][j] = dp[i - 1][j - 1];
                else
                    dp[i][j] = Math.min(dp[i - 1][j - 1] + 1, Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1));
            }
        }
        return dp[word1.length() - 1][word2.length() - 1];
    }
}

33 搜索旋转排序数组

public class Solution
{
    public int search(int[] nums, int target)
    {
        int l = 0, r = nums.length - 1, mid;
        if (nums.length == 0) return -1;
        while (l <= r)
        {
            mid = (l + r) / 2;
            if (nums[mid] == target) return mid;
            if (nums[0] <= nums[mid])
            {
                if (nums[0] <= target && target < nums[mid])
                    r = mid - 1;
                else
                    l = mid + 1;
            }
            else
            {
                if (nums[mid] < target && target <= nums[nums.length - 1])
                    l = mid + 1;
                else
                    r = mid - 1;
            }
        }
        return -1;
    }
}

4 寻找两个正序数组的中位数❗

public class Solution
{
    public double findMedianSortedArrays(int[] nums1, int[] nums2)
    {
        int length1 = nums1.length, length2 = nums2.length;
        int totalLength = length1 + length2;
        if (totalLength % 2 == 1)
        {
            int midIndex = totalLength / 2;
            double median = getKthElement(nums1, nums2, midIndex + 1);
            return median;
        }
        else
        {
            int midIndex1 = totalLength / 2 - 1, midIndex2 = totalLength / 2;
            double median = (getKthElement(nums1, nums2, midIndex1 + 1) + getKthElement(nums1, nums2, midIndex2 + 1)) / 2.0;
            return median;
        }
    }

    public int getKthElement(int[] nums1, int[] nums2, int k)
    {
        int length1 = nums1.length, length2 = nums2.length;
        int index1 = 0, index2 = 0;
        while (true)
        {
            // 边界情况
            if (index1 == length1)
                return nums2[index2 + k - 1];
            if (index2 == length2)
                return nums1[index1 + k - 1];
            if (k == 1)
                return Math.min(nums1[index1], nums2[index2]);

            // 正常情况
            int half = k / 2;
            int newIndex1 = Math.min(index1 + half, length1) - 1;
            int newIndex2 = Math.min(index2 + half, length2) - 1;
            int pivot1 = nums1[newIndex1], pivot2 = nums2[newIndex2];
            if (pivot1 <= pivot2)
            {
                k -= (newIndex1 - index1 + 1);
                index1 = newIndex1 + 1;
            }
            else
            {
                k -= (newIndex2 - index2 + 1);
                index2 = newIndex2 + 1;
            }
        }
    }
}