leecode更新
This commit is contained in:
parent
f72765f983
commit
4b8e8a7d65
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.markilue.leecode.greedy;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.greedy
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-02-12 10:28
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣435题 无重叠区间:
|
||||||
|
* 给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T11_1_EraseOverlapIntervals {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
// int[][] intervals = {{
|
||||||
|
// 1, 2
|
||||||
|
// }, {
|
||||||
|
// 2, 3
|
||||||
|
// }, {
|
||||||
|
// 3, 4
|
||||||
|
// }, {
|
||||||
|
// 1, 3
|
||||||
|
// }};
|
||||||
|
|
||||||
|
int[][] intervals = {{0, 2}, {1, 3}, {2, 4}, {3, 5}, {4, 6}};
|
||||||
|
System.out.println(eraseOverlapIntervals(intervals));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路:与上题11的射爆重叠气球的思路类似,只不过这题是需要去除的区间,还是按xstart进行排序
|
||||||
|
* 速度击败52.7%,内存击败15.57% 50ms
|
||||||
|
* @param intervals
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int eraseOverlapIntervals(int[][] intervals) {
|
||||||
|
|
||||||
|
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
|
||||||
|
|
||||||
|
for (int[] interval : intervals) {
|
||||||
|
System.out.println(Arrays.toString(interval));
|
||||||
|
}
|
||||||
|
|
||||||
|
int threshold = intervals[0][1];
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for (int i = 1; i < intervals.length; i++) {
|
||||||
|
if (intervals[i][0] < threshold) {
|
||||||
|
//需要移除
|
||||||
|
result++;
|
||||||
|
threshold = Math.min(intervals[i][1], threshold);
|
||||||
|
} else {
|
||||||
|
threshold = intervals[i][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方思路:根据xend右排序,记录不会重叠的位置,最后的结果就是总区间数n-不会重叠区间ans
|
||||||
|
* 因为是按右排序,所以不用考虑子集情况
|
||||||
|
* 速度击败98.28%,内存击败71% 47ms
|
||||||
|
* @param intervals
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int eraseOverlapIntervals1(int[][] intervals) {
|
||||||
|
if (intervals.length == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Arrays.sort(intervals, new Comparator<int[]>() {
|
||||||
|
@Override
|
||||||
|
public int compare(int[] o1, int[] o2) {
|
||||||
|
return o1[1] - o2[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
int n = intervals.length;
|
||||||
|
int right = intervals[0][1];
|
||||||
|
int ans = 1;
|
||||||
|
for (int i = 1; i < n; i++) {
|
||||||
|
if (intervals[i][0] >= right) {
|
||||||
|
ans++;
|
||||||
|
right = intervals[i][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n - ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方动态规划法:时间复杂度比较高O(n^2)
|
||||||
|
* @param intervals
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int eraseOverlapIntervals2(int[][] intervals) {
|
||||||
|
if (intervals.length == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.sort(intervals, new Comparator<int[]>() {
|
||||||
|
public int compare(int[] interval1, int[] interval2) {
|
||||||
|
return interval1[0] - interval2[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
int n = intervals.length;
|
||||||
|
int[] f = new int[n];
|
||||||
|
Arrays.fill(f, 1);
|
||||||
|
for (int i = 1; i < n; ++i) {
|
||||||
|
for (int j = 0; j < i; ++j) {
|
||||||
|
if (intervals[j][1] <= intervals[i][0]) {
|
||||||
|
f[i] = Math.max(f[i], f[j] + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n - Arrays.stream(f).max().getAsInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
package com.markilue.leecode.greedy;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.greedy
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-02-12 11:14
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣763题 划分字母区间:
|
||||||
|
* 给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。
|
||||||
|
* 注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。
|
||||||
|
* 返回一个表示每个字符串片段的长度的列表。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T11_2_PartitionLabels {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
String s = "eccbbbbdec";
|
||||||
|
System.out.println(partitionLabels(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路:Map记录<num,startIndex>,如果num不在map的话count+1重新分片,并把它加入map
|
||||||
|
* 速度击败7.77%,内存击败9.27% 10ms
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Integer> partitionLabels(String s) {
|
||||||
|
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
HashMap<Character, Integer> map = new HashMap<>();//<char,startIndex>
|
||||||
|
List<Integer> result = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
if (map.containsKey(chars[i])) {
|
||||||
|
Integer startIndex = map.get(chars[i]);
|
||||||
|
//看看需要更改result的位置
|
||||||
|
int lastThreshold = -1;//count转index
|
||||||
|
int count = 0;
|
||||||
|
for (; count < result.size(); count++) {
|
||||||
|
int index=result.get(count);
|
||||||
|
if (startIndex <= lastThreshold+index) {//count变index
|
||||||
|
//撞了
|
||||||
|
result.set(count, i - lastThreshold);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastThreshold += index;
|
||||||
|
}
|
||||||
|
//移除撞了之后的,全部变成一个
|
||||||
|
for (; result.size() > count + 1; ) {
|
||||||
|
result.remove(result.size() - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//没遇到过
|
||||||
|
result.add(1);
|
||||||
|
map.put(chars[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码随想录思路:本质上就是看那个字母出现的最远,如果遍历到了最远的位置还没有比她更远的,那么就把他加入result中;从而转换为11.1和11之中完全一样的解法了
|
||||||
|
* TODO
|
||||||
|
* 在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。
|
||||||
|
* 可以分为如下两步:
|
||||||
|
* 1.统计每一个字符最后出现的位置
|
||||||
|
* 2.从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
|
||||||
|
* 速度击败98.47% 内存击败38.58% 2ms
|
||||||
|
* @param S
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Integer> partitionLabels1(String S) {
|
||||||
|
List<Integer> list = new LinkedList<>();
|
||||||
|
int[] edge = new int[26];
|
||||||
|
char[] chars = S.toCharArray();
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
edge[chars[i] - 'a'] = i;
|
||||||
|
}
|
||||||
|
int idx = 0;
|
||||||
|
int last = -1;
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
idx = Math.max(idx, edge[chars[i] - 'a']);
|
||||||
|
if (i == idx) {
|
||||||
|
list.add(i - last);
|
||||||
|
last = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ import java.util.Comparator;
|
||||||
* 给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。
|
* 给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class FindMinArrowShots {
|
public class T11_FindMinArrowShots {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
package com.markilue.leecode.greedy.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.greedy.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-02-12 09:40
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣452题 用最少数量的箭引爆气球:
|
||||||
|
* 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。
|
||||||
|
* 一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。
|
||||||
|
* 在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被 引爆 。
|
||||||
|
* 可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。
|
||||||
|
* 给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T11_FindMinArrowShots {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test(){
|
||||||
|
int[][] points = {{9, 12}, {1, 10}, {4, 11}, {8, 12}, {3, 9}, {6, 9}, {6, 7}};
|
||||||
|
System.out.println(findMinArrowShots(points));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 思路:按xstart排序,当下一个的xstart大于上一个的xend那么就需要增加一支箭
|
||||||
|
* 速度击败81.41%,内存击败21.99% 53ms
|
||||||
|
* @param points
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int findMinArrowShots(int[][] points) {
|
||||||
|
|
||||||
|
Arrays.sort(points, (a, b) -> {
|
||||||
|
if(a[1]!=b[1]){
|
||||||
|
if(a[1]>b[1]){
|
||||||
|
return 1;
|
||||||
|
}else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if(a[0]>b[0]){
|
||||||
|
return 1;
|
||||||
|
}else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
int threshold = points[0][1];
|
||||||
|
int arrow = 1;
|
||||||
|
|
||||||
|
for (int i = 1; i < points.length; i++) {
|
||||||
|
if (threshold < points[i][0]) {
|
||||||
|
//不够了
|
||||||
|
arrow++;
|
||||||
|
threshold = points[i][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return arrow;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码随想录思路:与本人之前的思路类似,按xstart排序,如果是自己,更新threshold
|
||||||
|
* 速度击败68.99%,内存击败87.94% 54ms
|
||||||
|
* @param points
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int findMinArrowShots1(int[][] points) {
|
||||||
|
// 根据气球直径的开始坐标从小到大排序
|
||||||
|
// 使用Integer内置比较方法,不会溢出
|
||||||
|
Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
|
||||||
|
|
||||||
|
int count = 1; // points 不为空至少需要一支箭
|
||||||
|
for (int i = 1; i < points.length; i++) {
|
||||||
|
if (points[i][0] > points[i - 1][1]) { // 气球i和气球i-1不挨着,注意这里不是>=
|
||||||
|
count++; // 需要一支箭
|
||||||
|
} else { // 气球i和气球i-1挨着
|
||||||
|
points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue