本博客文章(学习笔记)导航 (点击这里访问)
BM87 合并两个有序的数组
描述
给出一个有序的整数数组 A 和有序的整数数组 B ,请将数组 B 合并到数组 A 中,变成一个有序的升序数组
数据范围:0≤n,m≤100,|A_i| <=100∣ |B_i| <= 100
注意:
1.保证 A 数组有足够的空间存放 B 数组的元素, A 和 B 中初始的元素数目分别为 m 和 n,A的数组空间大小为 m+n
2.不要返回合并的数组,将数组 B 的数据合并到 A 里面就好了,且后台会自动将合并后的数组 A 的内容打印出来,所以也不需要自己打印
3. A 数组在[0,m-1]的范围也是有序的
示例1
输入:[4,5,6],[1,2,3]
返回值:[1,2,3,4,5,6]
说明:A数组为[4,5,6],B数组为[1,2,3],后台程序会预先将A扩容为[4,5,6,0,0,0],B还是为[1,2,3],m=3,n=3,传入到函数merge里面,然后请同学完成merge函数,将B的数据合并A里面,最后后台程序输出A数组
示例2
输入:[1,2,3],[2,5,6]
返回值:[1,2,2,3,5,6]
思路:
1 双指针 合并数组 都放在A数组的末尾
import java. util. ;
public class Solution {
public void merge ( int A [ ] , int m, int B [ ] , int n) {
int index= m+ n- 1 , i= m- 1 , j= n- 1 ;
while ( i>= 0 && j>= 0 ) {
if ( A [ i] > B [ j] ) {
A [ index] = A [ i] ;
i-- ;
} else {
A [ index] = B [ j] ;
j-- ;
}
index-- ;
}
while ( j>= 0 ) {
A [ index] = B [ j] ;
index-- ;
j-- ;
}
}
}
BM88 判断是否为回文字符串
思路1:
反转字符串比较
思路2:
双指针
import java. util. ;
public class Solution {
public boolean judge ( String str) {
return str. equals ( new StringBuilder ( str) . reverse ( ) . toString ( ) ) ;
}
}
import java. util. ;
public class Solution {
public boolean judge ( String str) {
int i= 0 , j= str. length ( ) - 1 ;
while ( i< j) {
if ( str. charAt ( i) != str. charAt ( j) ) return false ;
i++ ;
j-- ;
}
return true ;
}
}
BM89 合并区间
描述
给出一组区间,请合并所有重叠的区间。请保证合并后的区间按区间起点升序排列。
数据范围:区间组数 0≤n≤2×10^5,区间内 的值都满足0^50≤val≤2×10^5
要求:空间复杂度 O(n),时间复杂度 O(nlogn)
进阶:空间复杂度 O(val),时间复杂度O(val)
示例1
输入:[[10,30],[20,60],[80,100],[150,180]]
返回值:[[10,60],[80,100],[150,180]]
示例2
输入:[[0,10],[10,20]]
返回值:[[0,20]]
思路:
1 按照区间第一个元素从小到大排序
2 遍历1到n-1个元素,判断是否可以合并区间
2.1 可以 设置i+1位置
2.2 不可以 添加进数组
时间复杂度:O(n) 空间复杂度:O(1)
import java. util. ;
/
Definition for an interval.
public class Interval {
int start;
int end;
Interval ( ) { start = 0 ; end = 0 ; }
Interval ( int s, int e) { start = s; end = e; }
}
/
public class Solution {
public ArrayList < Interval > merge ( ArrayList < Interval > intervals) {
ArrayList < Interval > res= new ArrayList < > ( ) ;
if ( intervals. size ( ) < 2 ) return intervals;
Collections . sort ( intervals, ( a, b) -> a. start- b. start) ;
for ( int i= 0 ; i< intervals. size ( ) - 1 ; i++ ) {
if ( intervals. get ( i) . end>= intervals. get ( i+ 1 ) . start) {
intervals. set ( i+ 1 , new Interval ( intervals. get ( i) . start, Math . max ( intervals. get ( i+ 1 ) . end, intervals. get ( i) . end) ) ) ;
} else {
res. add ( intervals. get ( i) ) ;
}
}
res. add ( intervals. get ( intervals. size ( ) - 1 ) ) ;
return res;
}
}
BM90 最小覆盖子串
描述
给出两个字符串 s 和 t,要求在 s 中找出最短的包含 t 中所有字符的连续子串。
数据范围:0 > ∣S ∣, ∣T ∣≤10000 ,保证s和t字符串中仅包含大小写英文字母
要求:进阶:空间复杂度 O ( n) , 时间复杂度 O ( n)
例如:
S = "XDOYEZODEYXNZ" S = "XDOYEZODEYXNZ"
T = "XYZ" T = "XYZ"
找出的最短子串为"YXNZ" "YXNZ".
注意:
如果 s 中没有包含 t 中所有字符的子串,返回空字符串 “”;
满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。
示例1
输入:"XDOYEZODEYXNZ" , "XYZ"
返回值:"YXNZ"
示例2
输入:"abcAbA" , "AA"
返回值:"AbA"
思路:
左闭右开 滑动窗口
1 排除掉特殊条件
2 用一个字符数组 记录所需的字符和个数
3 声明左指针、右指针、命中need的数量、字符开始的指针、最小长度
4 开始扩大窗口
4.1 判断当前位置是否命中need
命中
如果have < need count++
have++
r++
缩小窗口
左指针未命中need 直接缩小
左指针命中need 且 have==need 此时count--
不命中
r++
continue
class Solution {
public String minWindow ( String s, String t) {
if ( s == null || s == "" || t == null || t == "" || s. length ( ) < t. length ( ) ) {
return "" ;
}
int [ ] need = new int [ 128 ] ;
int [ ] have = new int [ 128 ] ;
for ( int i = 0 ; i < t. length ( ) ; i++ ) {
need[ t. charAt ( i) ] ++ ;
}
int left = 0 , right = 0 , min = s. length ( ) + 1 , count = 0 , start = 0 ;
while ( right < s. length ( ) ) {
char r = s. charAt ( right) ;
if ( need[ r] == 0 ) {
right++ ;
continue ;
}
if ( have[ r] < need[ r] ) {
count++ ;
}
have[ r] ++ ;
right++ ;
while ( count == t. length ( ) ) {
if ( right - left < min) {
min = right - left;
start = left;
}
char l = s. charAt ( left) ;
if ( need[ l] == 0 ) {
left++ ;
continue ;
}
if ( have[ l] == need[ l] ) {
count-- ;
}
have[ l] -- ;
left++ ;
}
}
if ( min == s. length ( ) + 1 ) {
return "" ;
}
return s. substring ( start, start + min) ;
}
}
BM91 反转字符串
描述
写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000)
数据范围:0≤n≤1000
要求:空间复杂度 O(n),时间复杂度 O(n)
示例1
输入:"abcd"
返回值:"dcba"
示例2
输入:""
返回值:""
思路1:
调用API
思路2:
双指针
import java. util. ;
public class Solution {
public String solve ( String str) {
return new StringBuilder ( str) . reverse ( ) . toString ( ) ;
}
}
import java. util. ;
public class Solution {
public String solve ( String str) {
char [ ] chars= str. toCharArray ( ) ;
int l= 0 , r= str. length ( ) - 1 ;
while ( l< r) {
char c= chars[ l] ;
chars[ l] = chars[ r] ;
chars[ r] = c;
l++ ;
r-- ;
}
return new String ( chars) ;
}
}
BM92 最长无重复子数组
描述
给定一个长度为n的数组arr,返回arr的最长无重复元素子数组的长度,无重复指的是所有数字都不相同。
子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组
数据范围:0≤arr.length≤10 5,0<arr[i]≤10^5
示例1
输入:[2,3,4,5]
返回值:4
说明:[2,3,4,5]是最长子数组
示例2
输入:[2,2,3,4,3]
返回值:3
说明:[2,3,4]是最长子数组
示例3
输入:[9]
返回值:1
示例4
输入:[1,2,3,1,2,3,2,2]
返回值:3
说明:最长子数组为[1,2,3]
示例5
输入:[2,2,3,4,8,99,3]
返回值:5
说明:最长子数组为[2,3,4,8,99]
思路:
滑动窗口,记录值和索引,重复的话直接从重复位置的下一个位置开始滑动
import java. util. ;
public class Solution {
public int maxLength ( int [ ] arr) {
if ( arr== null | arr. length== 0 ) return 0 ;
if ( arr. length== 1 ) return 1 ;
HashMap < Integer , Integer > map= new HashMap < > ( ) ;
int left= 0 , right= 0 , max= 1 ;
while ( right< arr. length) {
int r= arr[ right] ;
if ( ! map. containsKey ( r) ) {
map. put ( r, right) ;
} else {
int rindex= map. get ( r) ;
left= Math . min ( rindex+ 1 , right) ;
map= new HashMap < > ( ) ;
for ( int i= left; i<= right; i++ ) {
map. put ( arr[ i] , i) ;
}
}
right++ ;
max= Math . max ( right- left, max) ;
}
return max;
}
}
BM93 盛水最多的容器
描述
给定一个数组height,长度为n,每个数代表坐标轴中的一个点的高度,height[i]是在第i点的高度,请问,从中选2个高度与x轴组成的容器最多能容纳多少水
1.你不能倾斜容器
2.当n小于2时,视为不能形成容器,请返回0
3.数据保证能容纳最多的水不会超过整形范围,即不会超过231-1
数据范围: 0<=height.length<=10^5 0<=height[i]<=10^4
如输入的height为[1,7,3,2,4,5,8,2,7],那么如下图:
示例1
输入:[1,7,3,2,4,5,8,2,7]
返回值:49
示例2
输入:[2,2]
返回值:2
示例3
输入:[5,4,3,2,1,5]
返回值:25
思路:
双指针 每次移动最小的那根边
import java. util. ;
public class Solution {
public int maxArea ( int [ ] height) {
if ( height. length<= 1 ) return 0 ;
int l= 0 , r= height. length- 1 ;
int maxVolum= 0 ;
while ( l< r) {
int minSide= Math . min ( height[ l] , height[ r] ) ;
maxVolum= Math . max ( maxVolum, minSide ( r- l) ) ;
if ( height[ l] == minSide) {
l++ ;
} else {
r-- ;
}
}
return maxVolum;
}
}
BM94 接雨水问题
描述
给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。(数组以外的区域高度视为0)
数据范围:数组长度 0< n< 2 10^5,数组中每个值满足 0 < val <10^9,保证返回结果满足 0 < val < 10^9
要求:时间复杂度 O(n)
示例1
输入:[3,1,2,5,2,4]
返回值:5
说明:数组 [3,1,2,5,2,4] 表示柱子高度图,在这种情况下,可以接 5个单位的雨水,蓝色的为雨水 ,如题面图。
示例2
输入:[4,5,1,3,2]
返回值:2
思路1 :
双指针:
1 先找到最高的柱子
2 分别找左右两边能存水的值
左边: 当前位置的存水值=左侧最高值-当前值
右边: 当前位置的存水值=右侧最高值-当前值
思路2:
遍历每一层,高度为1、2、3...
左右不为空的中间夹层的个数
import java. util. ;
public class Solution {
public long maxWater ( int [ ] arr) {
int maxHeight= 0 , maxIndex= 0 ;
for ( int i= 0 ; i< arr. length; i++ ) {
if ( arr[ i] > maxHeight) {
maxIndex= i;
maxHeight= arr[ i] ;
}
}
int left= 0 , right= 0 , maxleftindex= 0 , maxrightindex= arr. length- 1 ;
for ( int i= 0 ; i< maxIndex; i++ ) {
if ( i== 0 ) continue ;
if ( arr[ i] < arr[ maxleftindex] ) {
left+= arr[ maxleftindex] - arr[ i] ;
} else {
maxleftindex= i;
}
}
for ( int i= arr. length- 1 ; i> maxIndex; i-- ) {
if ( i== arr. length- 1 ) continue ;
if ( arr[ i] < arr[ maxrightindex] ) {
right+= arr[ maxrightindex] - arr[ i] ;
} else {
maxrightindex= i;
}
}
return left+ right;
}
}