目录
1. 破解闯关密码
1.1. 题目描述
1.2. 解题思路
方法一:快速排序
class Solution {
public String crackPassword(int[] password) {
String[] strs = new String[password.length];
for(int i = 0; i < password.length; i++)
strs[i] = String.valueOf(password[i]);
quickSort(strs, 0, strs.length - 1);
StringBuilder res = new StringBuilder();
for(String s : strs)
res.append(s);
return res.toString();
}
void quickSort(String[] strs, int l, int r) {
if(l >= r) return;
int i = l, j = r;
String tmp = strs[i];
while(i < j) {
while((strs[j] + strs[l]).compareTo(strs[l] + strs[j]) >= 0 && i < j) j--;
while((strs[i] + strs[l]).compareTo(strs[l] + strs[i]) <= 0 && i < j) i++;
tmp = strs[i];
strs[i] = strs[j];
strs[j] = tmp;
}
strs[i] = strs[l];
strs[l] = tmp;
quickSort(strs, l, i - 1);
quickSort(strs, i + 1, r);
}
}
class Solution {
public String crackPassword(int[] password) {
String[] strs = new String[password.length];
for(int i = 0; i < password.length; i++)
strs[i] = String.valueOf(password[i]);
Arrays.sort(strs, (x, y) -> (x + y).compareTo(y + x));
StringBuilder res = new StringBuilder();
for(String s : strs)
res.append(s);
return res.toString();
}
}
2. 文物朝代判断
2.1. 题目描述
2.2. 解题思路
方法一: 辅助哈希表
class Solution {
public boolean checkDynasty(int[] places) {
Set<Integer> repeat = new HashSet<>();
int max = 0, min = 14;
for(int place : places) {
if(place == 0) continue; // 跳过未知朝代
max = Math.max(max, place); // 最大编号朝代
min = Math.min(min, place); // 最小编号朝代
if(repeat.contains(place)) return false; // 若有重复,提前返回 false
repeat.add(place); // 添加此朝代至 Set
}
return max - min < 5; // 最大编号朝代 - 最小编号朝代 < 5 则连续
}
}
方法二:排序 + 遍历
Java 代码:
class Solution {
public boolean checkDynasty(int[] places) {
int unknown = 0;
Arrays.sort(places); // 数组排序
for(int i = 0; i < 4; i++) {
if(places[i] == 0) unknown++; // 统计未知朝代数量
else if(places[i] == places[i + 1]) return false; // 若有重复,提前返回 false
}
return places[4] - places[unknown] < 5; // 最大编号朝代 - 最小编号朝代 < 5 则连续
}
}
3. 库存管理 III
3.1. 题目描述
3.2. 解题思路
方法一:排序
class Solution {
public int[] inventoryManagement(int[] stock, int cnt) {
int[] vec = new int[cnt];
stockays.sort(stock);
for (int i = 0; i < cnt; ++i) {
vec[i] = stock[i];
}
return vec;
}
}
方法二:堆
class Solution {
public int[] inventoryManagement(int[] stock, int cnt) {
int[] vec = new int[cnt];
if (cnt == 0) { // 排除 0 的情况
return vec;
}
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer num1, Integer num2) {
return num2 - num1;
}
});
for (int i = 0; i < cnt; ++i) {
queue.offer(stock[i]);
}
for (int i = cnt; i < stock.length; ++i) {
if (queue.peek() > stock[i]) {
queue.poll();
queue.offer(stock[i]);
}
}
for (int i = 0; i < cnt; ++i) {
vec[i] = queue.poll();
}
return vec;
}
}
方法三:快排思想
class Solution {
public int[] inventoryManagement(int[] stock, int cnt) {
randomizedSelected(stock, 0, stock.length - 1, cnt);
int[] vec = new int[cnt];
for (int i = 0; i < cnt; ++i) {
vec[i] = stock[i];
}
return vec;
}
private void randomizedSelected(int[] stock, int l, int r, int cnt) {
if (l >= r) {
return;
}
int pos = randomizedPartition(stock, l, r);
int num = pos - l + 1;
if (cnt == num) {
return;
} else if (cnt < num) {
randomizedSelected(stock, l, pos - 1, cnt);
} else {
randomizedSelected(stock, pos + 1, r, cnt - num);
}
}
// 基于随机的划分
private int randomizedPartition(int[] nums, int l, int r) {
int i = new Random().nextInt(r - l + 1) + l;
swap(nums, r, i);
return partition(nums, l, r);
}
private int partition(int[] nums, int l, int r) {
int pivot = nums[r];
int i = l - 1;
for (int j = l; j <= r - 1; ++j) {
if (nums[j] <= pivot) {
i = i + 1;
swap(nums, i, j);
}
}
swap(nums, i + 1, r);
return i + 1;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
4. 数据流的中位数
4.1 题目描述
4.2 解题思路
方法一:优先队列
class MedianFinder {
PriorityQueue<Integer> queMin;
PriorityQueue<Integer> queMax;
public MedianFinder() {
queMin = new PriorityQueue<Integer>((a, b) -> (b - a));
queMax = new PriorityQueue<Integer>((a, b) -> (a - b));
}
public void addNum(int num) {
if (queMin.isEmpty() || num <= queMin.peek()) {
queMin.offer(num);
if (queMax.size() + 1 < queMin.size()) {
queMax.offer(queMin.poll());
}
} else {
queMax.offer(num);
if (queMax.size() > queMin.size()) {
queMin.offer(queMax.poll());
}
}
}
public double findMedian() {
if (queMin.size() > queMax.size()) {
return queMin.peek();
}
return (queMin.peek() + queMax.peek()) / 2.0;
}
}
方法二:有序集合 + 双指针
Java代码:
class MedianFinder {
TreeMap<Integer, Integer> nums;
int n;
int[] left;
int[] right;
public MedianFinder() {
nums = new TreeMap<Integer, Integer>();
n = 0;
left = new int[2];
right = new int[2];
}
public void addNum(int num) {
nums.put(num, nums.getOrDefault(num, 0) + 1);
if (n == 0) {
left[0] = right[0] = num;
left[1] = right[1] = 1;
} else if ((n & 1) != 0) {
if (num < left[0]) {
decrease(left);
} else {
increase(right);
}
} else {
if (num > left[0] && num < right[0]) {
increase(left);
decrease(right);
} else if (num >= right[0]) {
increase(left);
} else {
decrease(right);
System.arraycopy(right, 0, left, 0, 2);
}
}
n++;
}
public double findMedian() {
return (left[0] + right[0]) / 2.0;
}
private void increase(int[] iterator) {
iterator[1]++;
if (iterator[1] > nums.get(iterator[0])) {
iterator[0] = nums.ceilingKey(iterator[0] + 1);
iterator[1] = 1;
}
}
private void decrease(int[] iterator) {
iterator[1]--;
if (iterator[1] == 0) {
iterator[0] = nums.floorKey(iterator[0] - 1);
iterator[1] = nums.get(iterator[0]);
}
}
}