This commit is contained in:
whai 2024-03-05 15:40:04 +08:00
parent bbb29153f5
commit 50cafa2cb5
5 changed files with 456 additions and 16 deletions

View File

@ -0,0 +1,108 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/4 15:46
* @注释
*/
public class LeetCode435 {
@Test
public void test() {
// intervals = [[1,2],[2,3],[3,4],[1,3]]
int[][] ints = {{1, 2}, {1, 3}, {2, 3}, {3, 4}};
System.out.println(new Solution1().eraseOverlapIntervals(ints));
}
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
int sub = 0;
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] <= intervals[i - 1][1]) {
sub++;
intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]);
}else {
intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]);
}
}
return sub;
}
}
class Solution1 {
/**
* 想象成一次性最多参加几个活动
* 按照结束时间排序
*
* 每次right边界就是取最早活动结束的时间
* 如果某次活动开始时间刚刚好比上一个活动结束的时间要晚那么就能多参加一次活动
*
* @param intervals
* @return
*/
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1];
}
});
int normalCount = 1;
int right = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
// 如果这次活动的开始时间比上个活动结束的时间要早那么这个活动就不参加了
if (intervals[i][0] >= right) {
// 如果这次活动的开始时间比上个活动结束的时间要晚那么这个活动就可以参加
// 最新的结束时间更新为这个活动的结束时间
right = intervals[i][1];
normalCount++;
}
}
return intervals.length - normalCount;
}
}
class Solution2 {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1];
}
});
int normalCount = 1;
for (int i = 1; i < intervals.length; i++) {
if (intervals[i - 1][1] <= intervals[i][0]) {
normalCount++;
} else {
// i的右边界有不重合则正常区间+1
intervals[i][1] = Math.min(intervals[i - 1][1], intervals[i][1]);
}
}
return intervals.length - normalCount;
}
}
}

View File

@ -0,0 +1,94 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/4 14:25
* @注释
*/
public class LeetCode452 {
@Test
public void test() {
// [[3,9],[7,12],[3,8],[6,8],[9,10],[2,9],[0,9],[3,9],[0,6],[2,8]]
int[][] ints = {
{3,9},{7,12},{3,8},{6,8},{9,10},{2,9},{0,9},{3,9},{0,6},{2,8}
};
System.out.println(new Solution1().findMinArrowShots(ints));
}
class Solution {
/**
*
* 按照最近出从小到大排序判断下一个区间是否有交集
* - 有交集取交集最小值作为都能bomb的点
* - 没有交集 res++表示下一个区间的箭
* @param points
* @return
*/
public int findMinArrowShots(int[][] points) {
// 先按首位从小到大排序end为start结束此区间全部bomb
Arrays.sort(points, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return Long.compare(o1[0], o2[0]);
}
});
int res = 1;
for (int i = 1; i < points.length; i++) {
if (points[i][0] < points[i - 1][1]) {
// 新的区间有交集
points[i][1] = Math.min(points[i][1], points[i - 1][1]);
}else {
res++;
}
}
return res;
}
}
class Solution1 {
/**
* 按照最远处排序判断下一元素是否在上一个的区间内不是就res++
* @param points
* @return
*/
public int findMinArrowShots(int[][] points) {
//按最远处从小到大排序
Arrays.sort(points, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
//-2147483646,-2147483645],[2147483646,2147483647 这个用例
return Long.compare(o1[1], o2[1]);
}
});
int res = 1;
int right = points[0][1];
for (int i = 1; i < points.length; i++) {
if (points[i][0] <= right) {
//当前箭能够射穿这个气球
continue;
}
res++;
right = points[i][1];
}
return res;
}
}
}

View File

@ -0,0 +1,60 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/5 12:09
* @注释
*/
public class LeetCode56 {
@Test
public void test() {
int[][] intervals = new int[][]{{1, 3}, {5, 6}};
for (int[] ints : new Solution().merge(intervals)) {
System.out.println(Arrays.toString(ints));
}
}
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
List<int[]> res = new ArrayList<>();
for (int i = 1; i < intervals.length; i++) {
if (intervals[i - 1][1] < intervals[i][0]) {
res.add(intervals[i - 1]);
} else {
intervals[i][0] = intervals[i - 1][0]; // 已经排序过了所以前一个的pre一定比这个的pre大
intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]);
}
}
res.add(intervals[intervals.length - 1]);
// int[][] result = new int[res.size()][2];
// for (int i = 0; i < res.size(); i++) {
// result[i] = res.get(i);
// }
// return result;
return res.toArray(new int[res.size()][2]);
}
}
}

View File

@ -0,0 +1,113 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/5 11:03
* @注释
*/
public class LeetCode763 {
@Test
public void test() {
new Solution1().partitionLabels("ababcbacadefegdehijhklij").forEach(
i -> {
System.out.println(i);
}
);
}
// 即最多能砍s多少刀使得同一字母都出现在一个片段
public List<Integer> partitionLabels(String s) {
// 统计 每个字符最远出现的位置
char[] chars = s.toCharArray();
int[] map = new int[26];
for (int i = 0; i < chars.length; i++) {
map[chars[i] - 'a'] = i;
}
List<Integer> res = new ArrayList<>();
// 再遍历idx最远的下标前面找到最远出现的位置==当前i 就是一个切断点
int left = -1; // 标记左边界
int far = 0; // 标记最远出现的
for (int i = 0; i < chars.length; i++) {
far = Math.max(far, map[chars[i] - 'a']); // far 表示最远边界
// 最远出现的 当前索引一样证明找到分割点
if (far == i) {
res.add(i - left);
left = i;
}
}
return res;
}
class Solution1 {
/**
* 先统计每个字符最早最晚出现的位置
* @param s
* @return
*/
public List<Integer> partitionLabels(String s) {
int[][] partitions = staticLabel(s.toCharArray());
List<Integer> res = new ArrayList<>();
Arrays.sort(partitions, (o1, o2) -> Integer.compare(o1[0], o2[0]));
int right = partitions[0][1];
int left = 0;
for (int i = 0; i < partitions.length; i++) {
if (partitions[i][0] > right) {
//左边界大于右边界即可纪委一次分割
res.add(right - left + 1);
left = partitions[i][0];
}
right = Math.max(right, partitions[i][1]);
}
//最右端
res.add(right - left + 1);
return res;
}
public int[][] staticLabel(char[] chars) {
int[][] map = new int[26][2];
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (map[c - 'a'][0] == 0) {
map[c - 'a'][0] = i;
}
map[c - 'a'][1] = i;//最远出现
//第一个元素区别对待一下
map[chars[0] - 'a'][0] = 0;
}
// 去除字符串中未出现的字母所占用区间
List<Integer> temp = new ArrayList<>();
List<List<Integer>> h = new LinkedList<>();
//组装区间
for (int i = 0; i < 26; i++) {
temp.clear();
temp.add(map[i][0]);
temp.add(map[i][1]);
h.add(new ArrayList<>(temp));
}
int[][] res = new int[h.size()][2];
for (int i = 0; i < h.size(); i++) {
List<Integer> list = h.get(i);
res[i][0] = list.get(0);
res[i][1] = list.get(1);
}
return map;
}
}
}

View File

@ -61,20 +61,85 @@ public class LeetCode406 {
}
class StringExer{
String str = new String("good");
char[] chars = {'a', 'b', 'c', 'd'};
//class StringExer{
// StringBuilder str = new StringBuilder("good");
// char[] chars = {'a', 'b', 'c', 'd'};
//
// public void change(StringBuilder str, char[] chars) {
// str = str.append("bad");
// chars[0] = 'e';
// }
//
// public static void main(String[] args) {
// StringExer stringExer = new StringExer();
// stringExer.change(stringExer.str, stringExer.chars);
// System.out.println(stringExer.str.toString());
// System.out.println(stringExer.chars);
//
// // 代码如下
// char[] f = {'a', 's', 'd'};
//
// String a = "asd"; // 常量池
// String b = new String("asd"); // 字符串形式new
// String c = new String(f); // 数组形式new
// String d = new String(f).intern(); // 数组形式new使用intern方法
// String b2 = new String("asd").intern(); // 字符串形式new
//
// System.out.println(a + b + c + d); // 断点打在这里只是为了防止jvm编译对代码优化
//
// System.out.println(a == b); // false
// System.out.println(a == b2); // true
// System.out.println(a == d); // true
// System.out.println(b == d); // false
// System.out.println(c == d); // false
//
//
// String a1 = new String("abc");
// String a2 = "abc";
// System.out.println(a1 == a2);
//
// }
//
//}
public void change(String str, char[] chars) {
str = "bad";
chars[0] = 'e';
}
public static void main(String[] args) {
StringExer stringExer = new StringExer();
stringExer.change(stringExer.str, stringExer.chars);
System.out.println(stringExer.str);
System.out.println(stringExer.chars);
}
}
//class ff {
// @Test
// public void main211() {
//
// /**
// * String s = new String("1")
// * 创建了两个对象
// * 堆空间中一个new对象
// * 字符串常量池中一个字符串常量"1"注意此时字符串常量池中已有"1"
// * s.intern()由于字符串常量池中已存在"1"
// * s指向的是堆空间中的对象地址
// * s2 指向的是堆空间中常量池中"1"的地址
// * 所以不相等
// */
// String s = new String("1");
// s.intern(); // 这里 常量池已经存在1
// String s2 = "1"; // 使用还是前面那个1
// System.out.println(s==s2); // 一指向堆一个指向常量池
//// jdk1.6 false jdk7/8 false
//
// /*
// * String s3 = new String("1") + new String("1")
// * 等价于new String"11"但是常量池中并不生成字符串"11"
// *
// * s3.intern()
// * 由于此时常量池中并无"11"所以把s3中记录的对象的地址存入常量池
// * 所以s3 s4 指向的都是一个地址
// */
// String s3 = new String("1") + new String("1");
//// 执行完后 常量池中不存在11
// s3.intern(); // 让常量池中存在11
//// 1. 在jdk6中intern() 如果没有会复制一份放入
//// 2. 在jdk7之后intern() 如果没有会把对象引用地址复制一份放入串池不会创建对象
// String s4 = "11"; // 使用上一行代码生成的11
// System.out.println(s3==s4);
////jdk1.6 false jdk7/8 true
//
// }
//
//
//}