Índice
128.A sequência contínua mais longa
452. Detonar o balão com o mínimo de flechas
128.A sequência contínua mais longa
Significado da pergunta:
Dado um array não classificado de inteiros
nums
, encontre o comprimento da sequência mais longa de números consecutivos (os elementos da sequência não precisam ser consecutivos no array original).Projete e implemente
O(n)
um algoritmo com complexidade de tempo para resolver este problema.
【Amostra de entrada】
números = [100,4,200,1,3,2]
【Amostra de saída】
4
Explicação: A sequência contínua mais longa de números é [1,2,3,4]
Ideias para resolução de problemas: tabela hash
1. Use set, que não contém elementos repetidos, portanto, primeiro armazenamos os elementos em nums no conjunto para obter um efeito de desduplicação.
2. Percorra o conjunto. Quando o dígito anterior num-1 de um número num não estiver na matriz, significa que pode ser o primeiro dígito da sequência contínua. Continue percorrendo para ver se o próximo dígito num+1 está em o conjunto.Se o comprimento estatístico existe até não ser encontrado.
class Solution {
public int longestConsecutive(int[] nums) {
int count = 0;
Set<Integer> numSet = new HashSet<>();
for(int num : nums){
numSet.add(num);
}
int tempCount;
for(int num : numSet){
if(!numSet.contains(num-1)){
tempCount = 1;//第一个数
while(numSet.contains(++num)){
++tempCount;//继续查找
}
count = Math.max(count,tempCount);
}
}
return count;
}
}
Tempo: bater 84,51%
Memória: Bata 89,54%
228. Intervalo de resumo
Significado da pergunta:
Dada uma matriz classificada de números inteiros sem elementos duplicados .
nums
Retorna uma lista dos menores intervalos ordenados que cobrem exatamente todos os números do array . Ou seja,
nums
cada elemento de é exatamente coberto por um determinado intervalo de intervalo, e não existe nenhumnums
número que pertença a um determinado intervalo, mas não o façax
.Cada intervalo de intervalo na lista
[a,b]
deve ser gerado no seguinte formato:
"a->b"
,sea != b
"a"
,sea == b
【Amostra de entrada】
números = [0,1,2,4,5,7]
【Amostra de saída】
["0->2","4->5","7"]
Ideias para resolução de problemas: enumeração
class Solution {
public List<String> summaryRanges(int[] nums) {
List<String> list = new ArrayList<>();
if(nums.length == 0){
return list;
}
if(nums.length == 1){
list.add(String.valueOf(nums[0]));
return list;
}
int i=0;
while(i < nums.length){
int low = i;
++i;
while(i<nums.length && nums[i] == nums[i-1]+1){
++i;
}
int high = i-1;
String str;
if(low == high){
str = String.valueOf(nums[low]);
}else{
str = nums[low]+"->"+nums[high];
}
list.add(str);
}
return list;
}
}
Tempo: Derrotado 51,34%
Memória: derrotada por 16,07%
56. Mesclar intervalos
Significado da pergunta:
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 .
【Amostra de entrada】
intervalos = [[1,3],[2,6],[8,10],[15,18]]
【Amostra de saída】
[[1,6],[8,10],[15,18]]
Ideias para resolução de problemas: classificação + julgamento de enumeração
1. Primeiro, classifique a matriz bidimensional fornecida em ordem crescente de acordo com o intervalo esquerdo.
2. Julgamento de enumeração, as variáveis leftBound e rightBound registram os limites esquerdo e direito atuais; enumeração, se o limite esquerdo do próximo intervalo for menor que o limite direito atual, prova que os dois intervalos podem ser mesclados e o limite direito é modificado (não modificar cegamente, para mudar para um valor maior, como (1,6), (2,4), a modificação direta se tornará (1,4), então você precisa julgar); se o limite esquerdo do O próximo intervalo é maior que rightBound, isso prova que os intervalos atuais não podem ser mesclados e são adicionados ao array.
class Solution {
public int[][] merge(int[][] intervals) {
List<int[]> res = new ArrayList<>();
//按照左边界排序
Arrays.sort(intervals, (x,y)-> Integer.compare(x[0],y[0]));
//initial start 是最小左边界
int leftBound = intervals[0][0];
int rightBound = intervals[0][1];//右边界
for(int i=1;i< intervals.length;++i){
//如果左边界大于上一个有边界
if(intervals[i][0] > rightBound){
//加入区间,更新start,加入的是上一个区间
res.add(new int[]{leftBound,rightBound});
leftBound = intervals[i][0];
rightBound = intervals[i][1];
}else{
//更新右边界
rightBound = Math.max(rightBound, intervals[i][1]);
}
}
res.add(new int[]{leftBound,rightBound});
return res.toArray(new int[res.size()][]);
}
}
Tempo: bater 80,99%
Memória: Bata 92,51%
57.Inserir intervalo
Significado da pergunta:
Fornece uma lista não sobreposta de intervalos classificados pelos pontos inicial e final dos intervalos.
Ao inserir um novo intervalo em uma lista, você precisa ter certeza de que os intervalos na lista ainda estão ordenados e não se sobrepõem (mesclando os intervalos, se necessário).
【Amostra de entrada】
intervalos = [[1,3],[6,9]], novoIntervalo = [2,5]
【Amostra de saída】
[[1,5],[6,9]]
Ideias para resolução de problemas: semelhante à pergunta anterior, mas esta questão não requer classificação
Enumere o intervalo original e considere quatro situações:
1. Quando o limite direito do i-ésimo elemento no intervalo original for menor que o limite esquerdo do intervalo inserido, insira o i-ésimo elemento diretamente no intervalo original;
2. Quando o limite esquerdo do i-ésimo elemento no intervalo original for maior que o limite direito do intervalo inserido, o novo intervalo é inserido e marcado como inserido. Quando esta situação for determinada posteriormente, os elementos do intervalo original são adicionados diretamente;
3. O terceiro caso, exceto 1 e 2, significa que o i-ésimo elemento do intervalo original se sobrepõe ao intervalo inserido, e os intervalos esquerdo e direito são atualizados julgando os valores máximo e mínimo dos dois intervalos .
4. Neste último caso, após o intervalo original ter sido percorrido e o novo intervalo não ter sido inserido, ele é inserido diretamente no final.
class Solution {
public int[][] insert(int[][] intervals, int[] newInterval) {
boolean isInsert = false;//是否已经插入
List<int[]> list = new ArrayList<>();
int leftBounds = newInterval[0];//新区间的左边界
int rightBounds = newInterval[1];//新区间的右边界
for(int i=0;i<intervals.length;++i){
if(intervals[i][0] > rightBounds){
if(!isInsert){
list.add(new int[]{leftBounds,rightBounds});
isInsert = true;
}
list.add(new int[]{intervals[i][0],intervals[i][1]});
}else if(intervals[i][1] < leftBounds){
//在插入区间的左侧
list.add(new int[]{intervals[i][0],intervals[i][1]});
}else{
//有交集,要合并区间
leftBounds = Math.min(leftBounds,intervals[i][0]);
rightBounds = Math.max(rightBounds,intervals[i][1]);
}
}
//如果遍历完还没有插入,添加到最后
if(!isInsert){
list.add(new int[]{leftBounds,rightBounds});
}
return list.toArray(new int[list.size()][]);
}
}
Tempo: bater 97,50%
Memória: derrotada por 67,95%
452. Detonar o balão com o mínimo de flechas
Significado da pergunta:
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
, quepoints[i] = [xstart, xend]
representam balões com diâmetros horizontais entrexstart
e .xend
Você 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 foremx
start
,x
end
, e forem satisfeitasxstart ≤ x ≤ x
end
, 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 .dica:
1 <= points.length <= 105
points[i].length == 2
-231 <= xstart < xend <= 231 - 1
【Amostra de entrada】
pontos = [[10,16],[2,8],[1,6],[7,12]]
【Amostra de saída】
2
Ideias para resolução de problemas: Semelhante a 56. Intervalo de mesclagem, a diferença é que ao atualizar o limite direito agora, você precisa pressionar o menor.
class Solution {
public int findMinArrowShots(int[][] points) {
//按照左边界排序
Arrays.sort(points, (x,y)-> Integer.compare(x[0],y[0]));
int result = 1;
for(int i=1;i< points.length;++i){
//如果左边界大于上一个有边界
if(points[i][0] > points[i-1][1]){
//加入区间,更新start,加入的是上一个区间
++result;
}else{
//更新右边界
points[i][1] = Math.min(points[i-1][1], points[i][1]);
}
}
// int result = res.size;
return result;
}
}
Tempo: Derrotado 18,88%
Memória: derrotada por 82,02%