LeetCode——Ganancioso (3)

Índice

452. Detonar um balão com o mínimo de flechas

435. Sem intervalos sobrepostos

763. Divida os intervalos das letras

56. Mesclar intervalos

738. Números monotonicamente crescentes

968. Monitore árvores binárias


A ordem e as ideias para responder às perguntas vêm do Code Caprice, endereço do site : https://programmercarl.com

452. Detonar um balão com o mínimo de flechas

Existem alguns balões esféricos presos a uma parede representada pelo plano XY. Os balões na parede são registrados em uma matriz de números inteiros  points , que points[i] = [xstart, xend] representam  balões com diâmetros horizontais entre xstart e  . xendVocê não sabe a coordenada y exata do balão.

Um arco e flecha podem ser disparados perfeitamente verticalmente a partir de diferentes pontos ao longo do eixo x   . Atire uma flecha nas coordenadas  x . Se as coordenadas inicial e final do diâmetro de um balão forem  xstart, xend, e forem satisfeitas   xstart ≤ x ≤ xend, o balão será  detonado  . Não há limite para o número de flechas que podem ser disparadas   . Depois que o arco e a flecha são disparados, ele pode avançar indefinidamente.

Você recebe um array  points que retorna o número mínimo  de flechas  que devem ser disparadas para explodir todos os balões  .

输入:points = [[10,16],[2,8],[1,6],[7,12]]
输出:2
解释:气球可以用2支箭来爆破:
-在x = 6处射出箭,击破气球[2,8]和[1,6]。
-在x = 11处发射箭,击破气球[10,16]和[7,12]。
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author light
 * @Description 452. 用最少数量的箭引爆气球
 *
 *
 * (思路:重叠在一起的气球用一只箭射出,
 * 但要注意重叠的右区间:如果下一个气球的左边界小于上一个重叠区间最小的右边界,则这个气球可以被同一只箭引爆
 * @create 2023-09-09 8:25
 */
public class FindMinArrowShotsTest {
	public static void main(String[] args) {
		int[][] points={
   
   {10,6},{2,8},{1,6},{7,12}};
		System.out.println(findMinArrowShots(points));

	}
	public static int findMinArrowShots(int[][] points) {
		//先将气球按最左区间从小到大排序
		//int 范围为-2147483648——2147483647,测试案例中会溢出
		Arrays.sort(points, new Comparator<int[]>() {
			@Override
			public int compare(int[] o1, int[] o2) {
				//return o1[0]-o2[0];
				return Integer.compare(o1[0],o2[0]); //采用Integer.compare()不会溢出
			}
		});
		int count=1; //气球不为空则至少需要一只箭
		for (int i = 1; i < points.length; i++) {
			if(points[i][0]>points[i-1][1]){
				count++;
			}else {
				points[i][1]=Math.min(points[i][1],points[i-1][1]);
			}
		}

		return count;
	}
}

435. Sem intervalos sobrepostos

Dado um conjunto de intervalos  intervals , onde  intervals[i] = [starti, endi] . Retorna  o número mínimo de intervalos que precisam ser removidos para que os intervalos restantes não se sobreponham  .

输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author light
 * @Description 无重叠区间
 *
 *
 * @create 2023-09-10 10:41
 */
public class EraseOverlapIntervalsTest {
	public static void main(String[] args) {
		int[][] intervals={
   
   {1,2},{2,3},{3,4},{1,3}};
		System.out.println(eraseOverlapIntervals(intervals));
	}
	public static int eraseOverlapIntervals(int[][] intervals) {
		//先将数组按左边界排序
		Arrays.sort(intervals, new Comparator<int[]>() {
			@Override
			public int compare(int[] o1, int[] o2) {
				return Integer.compare(o1[0],o2[0]);
			}
		});
		int count=0;//记录重叠区间数
		for (int i = 1; i < intervals.length; i++) {
			if(intervals[i][0]<intervals[i-1][1]){ //判断重叠情况
				count++;

				intervals[i][1]=Math.min(intervals[i][1],intervals[i-1][1]);
			}
		}
		return count;
	}
}

763. Divida os intervalos das letras

Você recebe uma string  s . Precisamos dividir essa string em tantos segmentos quanto possível, e a mesma letra aparece em no máximo um segmento.

Observe que os resultados da divisão precisam ser satisfeitos: todos os resultados da divisão são conectados em ordem e a sequência resultante ainda é  s .

Retorna uma lista que representa o comprimento de cada fragmento de string.

输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @author light
 * @Description 划分字母区间
 *
 * (思路:遍历字符串,找到每个字符的最远下标
 * @create 2023-09-10 11:07
 */
public class PartitionLabelsTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		String s=input.next();
		System.out.println(partitionLabels(s));
	}

	public static List<Integer> partitionLabels(String s) {
		List<Integer> list=new ArrayList<>(); //定义结果集
		int[] edge=new int[27]; //存放元素最远下标
		char[] arr=s.toCharArray();
		for (int i = 0; i < arr.length; i++) {
			edge[arr[i]-'a']=i;
		}
		int idx=0;
		int end=0;
		for (int i = 0; i < arr.length; i++) {
			idx=Math.max(idx,edge[arr[i]-'a']); //找到最远下标
			if(i==idx){
				list.add(idx-end+1); //将长度加入集合中
				end=i+1;
			}
		}
		return list;
	}
}

56. Mesclar intervalos

Use uma matriz  intervals para representar um conjunto de vários intervalos, onde um único intervalo é  intervals[i] = [starti, endi] . Mescle todos os intervalos sobrepostos e retorne  uma matriz de intervalos não sobrepostos que cubra exatamente todos os intervalos na entrada  .

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
public static int[][] merge(int[][] intervals) {
		List<int[]> list=new ArrayList<>();
		//将数组按左边界排序
		Arrays.sort(intervals, new Comparator<int[]>() {
			@Override
			public int compare(int[] o1, int[] o2) {
				return Integer.compare(o1[0],o2[0]);
			}
		});
		for (int i = 1; i < intervals.length; i++) {
			if(intervals[i][0]<=intervals[i-1][1]){
				//有重叠,合并区间---求右边界最大值,左区间最小值
				intervals[i][1]=Math.max(intervals[i-1][1],intervals[i][1]);
				intervals[i][0]=Math.min(intervals[i-1][0],intervals[i][0]);
			}else {
				list.add(intervals[i-1]);
			}
		}
		list.add(intervals[intervals.length-1]);
		return list.toArray(new int[list.size()][]);
	}

738. Números monotonicamente crescentes

 Dizemos que um número inteiro aumenta monotonicamente se e somente se a soma dos números em cada  x dígito  adjacente y for satisfatória  .x <= y

Dado um número inteiro  n , retorne   o maior número monotonicamente  crescente menor ou igual n a ele  .

输入: n = 10
输出: 9

import java.util.Scanner;

/**
 * @author light
 * @Description 单调递增的数字
。
 *
 * (思路:从后向前遍历数字,当遇到Num[i]<Num[i-1]时,只需要令Num[i]=9,Num[i-1]--即可,
 * @create 2023-09-10 13:40
 */
public class MonotoneIncreasingDigitsTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int n=input.nextInt();
		System.out.println(monotoneIncreasingDigits(n));
	}
	public static int monotoneIncreasingDigits(int n) {
		String s=String.valueOf(n);
		char[] arr=s.toCharArray();
		int flag=arr.length;
		for (int i =arr.length-1; i >0; i--) {
			if(arr[i-1]>arr[i]){
				arr[i-1]--;
				flag=i; //记录要变为9的下标起始位置
			}
		}
		for (int i = flag; i < arr.length; i++) {
			arr[i]='9';
		}
		return Integer.parseInt(String.valueOf(arr));
	}
}

968. Monitore árvores binárias

Dada uma árvore binária, instalamos câmeras nos nós da árvore.

Cada câmera em um nó pode monitorar seu pai, ela mesma e seus filhos diretos.

Calcule o número mínimo de câmeras necessárias para monitorar todos os nós da árvore.

 

    int count=0;
	public int minCameraCover(TreeNode root) {
		if(minCamera(root)==0){ //对根节点进行校验,防止根节点无覆盖
			count++;
		}
		return count;
	}

	private int minCamera(TreeNode root) {
		if(root==null){
			return 2;  //空节点---有覆盖
		}

		//左
		int left=minCamera(root.left);
		//右
		int right=minCamera(root.right);
		//中
		//1.左右孩子都有覆盖---中间父节点无覆盖
		if(left==2&&right==2){
			return 0;
		}else if(left==0||right==0){
			// 2.左右孩子至少一个无覆盖---中间结点父放摄像头
			count++;
			return 1;
		} else  {
			// 3.左右孩子有一个有摄像头---中间父节点有覆盖
			return 2;
		}

	}

Acho que você gosta

Origin blog.csdn.net/zssxcj/article/details/132776938
Recomendado
Clasificación