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;
}
}
}
}