class Solution {
class Solution {
public String removeKdigits(String num, int k) {
Deque<Character> stk = new ArrayDeque<>();
for (char c : num.toCharArray()) {
while (!stk.isEmpty() && c < stk.getLast() && k > 0) {
stk.pollLast();
k--;
}
stk.addLast(c);
}
String res = stk.stream().map(Object::toString).collect(Collectors.joining());
res = res.substring(0, res.length() - k).replaceAll("^0+", "");
return res.isEmpty() ? "0" : res;
}
}
class Solution {
public String removeDuplicateLetters(String S) {
char[] s = S.toCharArray();
int[] left = new int[26];
for (char c : s)
left[c - 'a']++; // 统计每个字母的出现次数
StringBuilder ans = new StringBuilder(26);
boolean[] inAns = new boolean[26];
for (char c : s) {
left[c - 'a']--;
if (inAns[c - 'a']) // ans 中不能有重复字母
continue;
// 设 x = ans.charAt(ans.length() - 1),
// 如果 c < x,且右边还有 x,那么可以把 x 去掉,因为后面可以重新把 x 加到 ans 中
while (!ans.isEmpty() && c < ans.charAt(ans.length() - 1) && left[ans.charAt(ans.length() - 1) - 'a'] > 0) {
inAns[ans.charAt(ans.length() - 1) - 'a'] = false; // 标记 x 不在 ans 中
ans.deleteCharAt(ans.length() - 1);
}
ans.append(c); // 把 c 加到 ans 的末尾
inAns[c - 'a'] = true; // 标记 c 在 ans 中
}
return ans.toString();
}
}
class Solution {
public int firstUniqChar(String s) {
Map<Character,Integer> frequency = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
frequency.put(ch, frequency.getOrDefault(ch,0)+1);
}
for (int i = 0; i < s.length(); i++) {
if (frequency.get(s.charAt(i)) == 1) {
return i;
}
}
return -1;
}
}
class RecentCounter {
Queue<Integer> queue;
public RecentCounter() {
queue = new ArrayDeque<Integer>();
}
public int ping(int t) {
queue.offer(t);
while (queue.peek() < t - 3000) {
queue.poll();
}
return queue.size();
}
}
class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
int n = nums1.length, m = nums2.length;
var ans = new ArrayList<List<Integer>>();
var pq = new PriorityQueue<int[]>((a, b) -> a[0] - b[0]);
for (int i = 0; i < Math.min(n, k); i++) // 至多 k 个
pq.add(new int[]{nums1[i] + nums2[0], i, 0});
while (!pq.isEmpty() && ans.size() < k) {
var p = pq.poll();
int i = p[1], j = p[2];
ans.add(List.of(nums1[i], nums2[j]));
if (j + 1 < m)
pq.add(new int[]{nums1[i] + nums2[j + 1], i, j + 1});
}
return ans;
}
}
class Solution {
public int nthUglyNumber(int n) {
int[] factors = {2, 3, 5};
Set<Long> seen = new HashSet<Long>();
PriorityQueue<Long> heap = new PriorityQueue<Long>();
seen.add(1L);
heap.offer(1L);
int ugly = 0;
for (int i = 0; i < n; i++) {
long curr = heap.poll();
ugly = (int) curr;
for (int factor : factors) {
long next = curr * factor;
if (seen.add(next)) {
heap.offer(next);
}
}
}
return ugly;
}
}
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = 0, p2 = 0;
int[] sorted = new int[m + n];
int cur;
while (p1 < m || p2 < n) {
if (p1 == m) {
cur = nums2[p2++];
} else if (p2 == n) {
cur = nums1[p1++];
} else if (nums1[p1] < nums2[p2]) {
cur = nums1[p1++];
} else {
cur = nums2[p2++];
}
sorted[p1 + p2 - 1] = cur;
}
for (int i = 0; i != m + n; ++i) {
nums1[i] = sorted[i];
}
}
}
class Solution {
public int compareVersion(String version1, String version2) {
String[] v1 = version1.split("\\.");
String[] v2 = version2.split("\\.");
for (int i = 0; i < v1.length || i < v2.length; ++i) {
int x = 0, y = 0;
if (i < v1.length) {
x = Integer.parseInt(v1[i]);
}
if (i < v2.length) {
y = Integer.parseInt(v2[i]);
}
if (x > y) {
return 1;
}
if (x < y) {
return -1;
}
}
return 0;
}
}
class Solution {
static final int L = 10;
public List<String> findRepeatedDnaSequences(String s) {
List<String> ans = new ArrayList<String>();
Map<String, Integer> cnt = new HashMap<String, Integer>();
int n = s.length();
for (int i = 0; i <= n - L; ++i) {
String sub = s.substring(i, i + L);
cnt.put(sub, cnt.getOrDefault(sub, 0) + 1);
if (cnt.get(sub) == 2) {
ans.add(sub);
}
}
return ans;
}
}
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer> list = new ArrayList<>();
int n = arr.length;
int left = 0;
int right = 0;
int sum = 0;
int res = Integer.MAX_VALUE;
int idx = 0;
while (right < n) {
sum += Math.abs(arr[right] - x);
if (right - left + 1 == k) { //固定窗口大小为k
if (sum < res) {
res = sum;
idx = left;
}
sum -= Math.abs(arr[left] - x);
left++;
}
right++;
}
for (int i = idx; i < idx + k; i++) {
list.add(arr[i]);
}
return list;
}
}
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummy = new ListNode(0, head), p0 = dummy;
for (int i = 0; i < left - 1; ++i)
p0 = p0.next;
ListNode pre = null, cur = p0.next;
for (int i = 0; i < right - left + 1; ++i) {
ListNode nxt = cur.next;
cur.next = pre; // 每次循环只修改一个 next,方便大家理解
pre = cur;
cur = nxt;
}
// 见视频
p0.next.next = cur;
p0.next = pre;
return dummy.next;
}
}
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int length = nums.length;
for (int i = 0; i < length; i++) {
int num = nums[i];
if (map.containsKey(num) && i - map.get(num) <= k) {
return true;
}
map.put(num, i);
}
return false;
}
}