排序相关
leetcode56合并区间
- 贪心思想
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, Comparator.comparingInt(o -> o[0]));
int first = intervals[0][0];
int points = intervals[0][1];
List<int[]> list = new ArrayList<>();
int i = 0;
while (true) {
while (i < intervals.length && intervals[i][0] <= points) {
points = Math.max(points, intervals[i][1]);
i++;
}
list.add(new int[]{first, points});
if (i == intervals.length) break;
first = intervals[i][0];
points = intervals[i][1];
}
return list.toArray(new int[list.size()][2]);
}
}
leetcode315计算右侧小于当前元素的个数🔐
- 归并排序和数组索引,通过比较元素变换索引来进行模拟排序
class Solution {
private int[] index;
private int[] helper;
private int[] count;
public List<Integer> countSmaller(int[] nums) {
int N = nums.length;
List<Integer> res = new ArrayList<>(N);
index = new int[N];
helper = new int[N];
count = new int[N];
for (int i = 0; i < index.length; i++) {
index[i] = i;
}
merge(nums, 0, nums.length - 1);
for (int value : count) {
res.add(value);
}
return res;
}
private void merge(int[] nums, int s, int e) {
if (s >= e) return;
int mid = (s + e) >> 1;
merge(nums, s, mid);
merge(nums, mid + 1, e);
process(nums, s, mid, e);
}
private void process(int[] nums, int s, int mid, int e) {
int i = s, j = mid + 1;
int hi = s;
while (i <= mid && j <= e) {
if (nums[index[i]] <= nums[index[j]]) {// 右侧出
helper[hi++] = index[j++];
} else {// 左侧出 计数
count[index[i]] += e - j + 1;
helper[hi++] = index[i++];
}
}
while (i <= mid) helper[hi++] = index[i++];//左侧出
while (j <= e) helper[hi++] = index[j++];// 右侧出
System.arraycopy(helper, s, index, s, e + 1 - s);
}
}
leetcode179最大数
class Solution {
public String largestNumber(int[] nums) {
String[] str = new String[nums.length];
for (int i = 0; i < str.length; i++) str[i] = String.valueOf(nums[i]);
Arrays.sort(str, ((o1, o2) -> (o2 + o1).compareTo(o1 + o2)));
StringBuffer res = new StringBuffer();
for (String s : str) res.append(s);
return res.toString().charAt(0) == '0' ? "0" : res.toString();
}
}
leetcode220存在重复元素 III🔐
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
int n = nums.length;
TreeSet<Long> ts = new TreeSet<>();
for (int i = 0; i < n; i++) {
Long u = nums[i] * 1L;
// 从 ts 中找到小于等于 u 的最大值(小于等于 u 的最接近 u 的数)
Long l = ts.floor(u);
// 从 ts 中找到大于等于 u 的最小值(大于等于 u 的最接近 u 的数)
Long r = ts.ceiling(u);
if(l != null && u - l <= t) return true;
if(r != null && r - u <= t) return true;
// 将当前数加到 ts 中,并移除下标范围不在 [max(0, i - k), i) 的数(维持滑动窗口大小为 k)
ts.add(u);
if (i >= k) ts.remove(nums[i - k] * 1L);
}
return false;
}
}
leetcode324摆动排序 II🔐
class Solution {
public void wiggleSort(int[] nums) {
if (nums.length <= 1) return;
Arrays.sort(nums);
int[] temp = new int[nums.length];
int k = nums.length - 1;
for (int i = 1; i < nums.length; i += 2) {
temp[i] = nums[k--];
}
for (int i = 0; i < nums.length; i += 2) {
temp[i] = nums[k--];
}
System.arraycopy(temp,0,nums,0,temp.length);
}
}
leetcode57插入区间
class Solution {
public int[][] insert(int[][] intervals, int[] newInterval) {
int idx = 0;
List<int[]> res = new ArrayList<>();
while (idx < intervals.length && intervals[idx][1] < newInterval[0]) { //寻找需要合并的区间
res.add(intervals[idx]);
idx++;
}
while (idx < intervals.length && intervals[idx][0] <= newInterval[1]) { //待合并区间头小于当前区间尾
newInterval[0] = Math.min(newInterval[0], intervals[idx][0]); //更新待合并区间头
newInterval[1] = Math.max(newInterval[1], intervals[idx][1]); //更新待合并区间尾
idx++;
}
res.add(newInterval);// 加入合并区间
while (idx < intervals.length) { // 加入剩余区间
res.add(intervals[idx++]);
}
return res.toArray(new int[res.size()][]);
}
}
leetcode274H指数
class Solution {
public int hIndex(int[] citations) {
int[] res = new int[1001];
for (int val : citations) {
res[val]++;
}
for (int i = 999; i >= 0; i--) {
res[i] += res[i + 1];
}
for (int i = 1000; i >= 0; i--) {
if (res[i] >= i) return i;
}
return 0;
}
}
leetcode164最大区间🔐
class Solution {
public int maximumGap(int[] nums) {
if (nums == null || nums.length < 2) {
return 0;
}
int len = nums.length;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int value : nums) {
min = Math.min(min, value);
max = Math.max(max, value);
}
if (min == max) {
return 0;
}
// 记录桶中是否存在值
boolean[] hasNum = new boolean[len + 1];
int[] maxs = new int[len + 1];
int[] mins = new int[len + 1];
int bid = 0;
// 由于多一个桶,那么其中一个桶定为空,最大差值定比一个桶的范围大
// 最大差值定比的两个数定在不同的桶中,选出每个桶中的最大值最小值
for (int num : nums) {
bid = bucket(num, len, min, max);// 该数应该在桶中的下标
// 更新桶中的最大最小值
mins[bid] = hasNum[bid] ? Math.min(mins[bid], num) : num;
maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], num) : num;
hasNum[bid] = true;
}
int res = 0;
int lastMax = maxs[0];
// 最大差值定存在于不同的桶中
for (int i = 1; i <= len; i++) {
if (hasNum[i]) {
res = Math.max(res, mins[i] - lastMax);
lastMax = maxs[i];// 记录该桶的最大值,用于后续不同桶的最大差值的比较
}
}
return res;
}
// 计算桶的下标索引
public static int bucket(long num, long len, long min, long max) {
return (int) ((num - min) * len / (max - min));
}
}