leecode更新

This commit is contained in:
markilue 2022-11-18 14:49:22 +08:00
parent 32ebfcceb8
commit 467586e982
3 changed files with 303 additions and 3 deletions

View File

@ -29,13 +29,14 @@ public class FindMinArrowShots {
// System.out.println((long)(-2147483646)-(long)(2147483647)); //-4294967293
// System.out.println((int)((long)(-2147483646)-(long)(2147483647)));//3
// System.out.println((int)(-2147483646)-(int)(2147483647)); //3
System.out.println(findMinArrowShots(points));
System.out.println(findMinArrowShots(points5));
}
/**
* 本人思路先根据xstart进行排序然后寻找第一个比xend大的xstart则result+1以此类推
* 排序的时间复杂度为O(nlogn),所以总复杂度为O(nlogn)
* 速度击败12.72%内存击败88.71%
* 速度击败12.72%内存击败88.71% =>修改compare方法后速度击败97.21%内存击败91.4% 耗时52ms
* 代码随想录方法与本人一致
* @param points
* @return
*/
@ -46,7 +47,15 @@ public class FindMinArrowShots {
@Override
public int compare(int[] o1, int[] o2) {
//警惕两数相减超过int范围
return o1[0] == o2[0] ? (o1[1] > o2[1]?1:-1) : (o1[0] > o2[0]?1:-1);
// return o1[0] == o2[0] ? (o1[1] > o2[1]?1:-1) : (o1[0] > o2[0]?1:-1);
//这里改为一层if速度超过97.21%
if(o1[0] > o2[0]){
return 1;
}else if(o1[0] < o2[0]){
return -1;
}else{
return 0;
}
}
});
@ -70,4 +79,45 @@ public class FindMinArrowShots {
return result;
}
/**
* 官方思路先根据xend进行排序然后寻找第一个比xend大的xstart则result+1以此类推
* 排序的时间复杂度为O(nlogn),所以总复杂度为O(nlogn)
* 速度击败30.68%内存击败69.54% 59ms 这个应该有bug次次提交不一样本质上应该比本人方法好每次for都少判断一次
* @param points
* @return
*/
public int findMinArrowShots1(int[][] points) {
//按xend进行排序
Arrays.sort(points, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
//这里两层if不太好改为if写法,官方按xend进行排序
if (o1[1] > o2[1]) {
return 1;
} else if (o1[1] < o2[1]) {
return -1;
} else {
return 0;
}
}
});
//遍历points找到比xend大的xstart就+1
int result=1;
int lastEnd=points[0][1];
for (int i = 1; i < points.length; i++) {
if(points[i][0]>lastEnd){
result++;
lastEnd=points[i][1];
}
}
return result;
}
}

View File

@ -0,0 +1,113 @@
package com.markilue.leecode.greedy;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.greedy
* @Author: markilue
* @CreateTime: 2022-11-18 10:58
* @Description: TODO 力扣56题 合并区间
* 以数组 intervals 表示若干个区间的集合其中单个区间为 intervals[i] = [starti, endi] 请你合并所有重叠的区间并返回 一个不重叠的区间数组该数组需恰好覆盖输入中的所有区间
* @Version: 1.0
*/
public class Merge {
@Test
public void test() {
int[][] points = {{1, 2}, {3, 4},{5, 6},{7, 8}};
int[][] points1 = {{1, 3}, {2, 6},{8, 10},{15, 18}};
int[][] points2 = {{1, 2}, {2, 3},{3, 4},{4, 5}};
int[][] points3 = {{1, 4}, {0, 4}};
int[][] points4 = {{-2147483646, -2147483645}, {2147483646, 2147483647}};
int[][] points5 = {{2,3}, {2, 2},{3, 3},{1, 3}, {5, 7}, {2, 2},{4, 6}};
// System.out.println((long)(-2147483646)-(long)(2147483647)); //-4294967293
// System.out.println((int)((long)(-2147483646)-(long)(2147483647)));//3
// System.out.println((int)(-2147483646)-(int)(2147483647)); //3
int[][] merge = merge(points2);
for (int[] ints : merge) {
System.out.println(Arrays.toString(ints));
}
}
/**
* 本人思路:与射箭那题类似本质上是找到重叠区间因此仍然是按xstart排序然后再一次循环寻找重叠区间
* 速度击败71.63%内存击败90.55% 7ms =>compare优化以后 速度击败97.55%内存击败53.75%
* @param intervals
* @return
*/
public int[][] merge(int[][] intervals) {
//按xstart排序
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
// if(o1[0]>o2[0]){
// return 1;
// } else if (o1[0]<o2[0]) {
// return -1;
// }else {
// return 0;
// }
//优化
return o1[0] - o2[0];
}
});
//寻找重叠区间并进行合并
int length=0;//记录新数组的长度
int[][] result =new int[intervals.length][2];
result[0]=intervals[0];
int lastEnd=intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if(lastEnd>=intervals[i][0]){
//重叠区间需要合并
lastEnd=Math.max(lastEnd,intervals[i][1]);
result[length][1]=lastEnd;
}else {
//非重叠区间直接添加
length++;
result[length]=intervals[i];
lastEnd=intervals[i][1];
}
}
//缩短至result的真实长度
return Arrays.copyOf(result,length+1);
}
/**
* 官方代码:与本人类似并使用动态扩容的arrayList记录添加
* 速度击败97.55%内存击败9.14%
* @param intervals
* @return
*/
public int[][] merge1(int[][] intervals) {
if (intervals.length == 0) {
return new int[0][2];
}
Arrays.sort(intervals, new Comparator<int[]>() {
public int compare(int[] interval1, int[] interval2) {
return interval1[0] - interval2[0];
}
});
List<int[]> merged = new ArrayList<int[]>();
for (int i = 0; i < intervals.length; ++i) {
int L = intervals[i][0], R = intervals[i][1];
if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) {
merged.add(new int[]{L, R});
} else {
merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R);
}
}
return merged.toArray(new int[merged.size()][]);
}
}

View File

@ -0,0 +1,137 @@
package com.markilue.leecode.greedy;
import org.junit.Test;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.greedy
* @Author: markilue
* @CreateTime: 2022-11-18 11:44
* @Description: TODO 力扣738题 单调递增的数字:
* 当且仅当每个相邻位数上的数字 x y 满足 x <= y 我们称这个整数是单调递增的
* 给定一个整数 n 返回 小于或等于 n 的最大数字且数字呈 单调递增
* @Version: 1.0
*/
public class MonotoneIncreasingDigits {
@Test
public void test() {
int n = 1234;
int n1 = 10;
int n2 = 332;
int n3=15;
System.out.println(monotoneIncreasingDigits2(n2));
}
/**
* 本人思路:可以发现的是如果一个数最高位小于其后一位那么无论如何都是需要把最高位减1的而这时后面的数就可以随便取9了后续位依次类推直至/10=0为止
* 这里有个矛盾的点是我们需要从最高位开始判但是事实上我们不知道数字具体有多少位只能不断/10来判 =>因此可以把n转为string获取长度
*
* 速度击败94.57%内存击败33.72%
* @param n
* @return
*/
public int monotoneIncreasingDigits(int n) {
String s = n + "";
int length = s.length();
if (length == 1) {
return n;
}
int[] num = new int[length];
num[0]=n%10;
int index=1;
n=n/10;
//这里仍然使用从后往前遍历因为如果从前往后后续又出现借的情况前面的逻辑可能有需要重新判一次
while (n>0&&n/10>=0){
int now = n%10;
if(now>num[index-1]){
now=now-1;
//当前减1后面全9
num[index]=now;
for (int i = 0; i <= index - 1; i++) {
num[i]=9;
}
}else {
num[index]=now;
}
n=n/10;
index++;
}
int result=0;
for (int i = length-1; i >= 0; i--) {
result*=10;
result+=num[i];
}
return result;
}
/**
* 官方题解:从前往后遍历找到不合题解的位置则把前面的数-1后面的数全部置为9
* 这种其实是比本人的优化的因为本人是从后往前遍历因此置为9的循环操作可能会持续很多次
* 速度击败94.57%内存击败57.77%
* @param n
* @return
*/
public int monotoneIncreasingDigits1(int n) {
char[] strN = Integer.toString(n).toCharArray();
int i = 1;
while (i < strN.length && strN[i - 1] <= strN[i]) {
i += 1;
}
if (i < strN.length) {
//找到不合适的位置一次性全部完成所以最多只需要执行一次置为9循环
while (i > 0 && strN[i - 1] > strN[i]) {
strN[i - 1] -= 1;
i -= 1;
}
for (i += 1; i < strN.length; ++i) {
strN[i] = '9';
}
}
return Integer.parseInt(new String(strN));
}
/**
* 评论里的题解:整体思路和官方差不多但是他用n - Integer.parseInt(s.substring(1)) - 1;这种操作避免了for循环速度增加
* 速度击败100%内部击败79.4%
*
* @param n
* @return
*/
public int monotoneIncreasingDigits2(int n) {
if (n < 10){
return n;
}
String s = Integer.toString(n);
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) < s.charAt(i - 1)){
int temp = i - 1;
while (true){
if (temp == 0){
return n - Integer.parseInt(s.substring(1)) - 1; //整体需要少一位所以n-他后面的数-1如1056-056-1=999
}else if (s.charAt(temp) - s.charAt(temp - 1) >= 1){ //当前数与前面的数之差大于1则放心的把当前数减1
return n - Integer.parseInt(s.substring(temp + 1)) - 1;//如1306-06-1=1299
}
temp--;//如果相差小于1了则不能直接减因此从上一个点来看看
}
}
}
return n;
}
}