本周每日一题 题目
lc240. 搜索二维矩阵 II
lc496. 下一个更大元素 I
lc301. 删除无效的括号
lc869. 重新排序得到 2 的幂
lc260. 只出现一次的数字 III
10-25 lc240. 搜索二维矩阵 II
周日忙着刷科四的题和科三练车,所以题就没刷,27号补上。一天刷了1k道科四的题,最后科四也是满分了,基本所有题全都背下来了,我觉得还是有必要的,毕竟以后要上路的
这题是简单题,有排序的矩阵二分查找,比较简单,没啥好说的
class Solution {
public boolean searchMatrix ( int [ ] [ ] matrix, int target) {
if ( matrix== null || matrix. length== 0 || matrix[ 0 ] . length== 0 ) return false ;
int m = matrix. length, n = matrix[ 0 ] . length;
int i = m- 1 , j = 0 ;
while ( i< m& & i> = 0 && j< n& & j> = 0 ) {
if ( matrix[ i] [ j] < target) j++ ;
else if ( matrix[ i] [ j] > target) i-- ;
else return true ;
}
return false ;
}
}
10-26 lc496. 下一个更大元素 I
当天去考驾照了,所以27号补的,顺利拿到驾照哈哈哈
本题就是对每个nums1中的元素,找到在nums2中下一个第一个大的元素即可,没有这个元素或者没有下一个第一个大的元素,就填-1
因为要保证O(N1+N2)的时间复杂度,所以需要牺牲一定的空间
那么思路很简单,先统计nums2的每个元素下一个第一个大的情况,放进map,然后再去遍历nums1,从map中获取,填入结果数组 即可
class Solution {
public int [ ] nextGreaterElement ( int [ ] nums1, int [ ] nums2) {
Map < Integer , Integer > map = new HashMap < > ( ) ;
Deque < Integer > stack = new LinkedList < > ( ) ;
for ( int i= nums2. length- 1 ; i>= 0 ; i-- ) {
while ( ! stack. isEmpty ( ) && stack. peek ( ) <= nums2[ i] ) stack. pop ( ) ;
map. put ( nums2[ i] , stack. isEmpty ( ) ? - 1 : stack. peek ( ) ) ;
stack. push ( nums2[ i] ) ;
}
int [ ] res = new int [ nums1. length] ;
for ( int i= 0 ; i< nums1. length; i++ ) res[ i] = map. getOrDefault ( nums1[ i] , - 1 ) ;
return res;
}
}
10-27 lc301. 删除无效的括号
因为要所有可能的结果,所以要穷举所有的结果
用bfs,每次删除一个括号,每个位置都有可能删除
思路就是把每个位置都尝试删除,然后放进set里进行下一次遍历
因为是bfs,所以当有一个已经符合的时候,此时已经达到最小路径了,即删除最小数量的括号,那么这一轮循环必须结束
class Solution {
public List < String > removeInvalidParentheses ( String s) {
Set < String > set = new HashSet < > ( ) ;
set. add ( s) ;
List < String > res = new ArrayList < > ( ) ;
boolean flag = false ;
while ( ! set. isEmpty ( ) && ! flag) {
Set < String > curSet = new HashSet < > ( ) ;
for ( String str: set) {
if ( check ( str) ) {
res. add ( str) ;
flag = true ;
}
if ( flag) continue ;
int n = str. length ( ) ;
for ( int i= 0 ; i< n; i++ ) {
char ch = str. charAt ( i) ;
if ( ch!= '(' && ch!= ')' ) continue ;
curSet. add ( str. substring ( 0 , i) + str. substring ( i+ 1 , n) ) ;
}
}
set = curSet;
}
return res;
}
private static boolean check ( String s) {
char [ ] ss = s. toCharArray ( ) ;
int l= 0 , r= 0 ;
for ( char ch: ss) {
if ( ch== '(' ) l++ ;
else if ( ch== ')' ) r++ ;
if ( l< r) return false ;
}
return l== r;
}
}
10-28 lc869. 重新排序得到 2 的幂
本题最简单,最取巧,最聪明的做法是列举出所有的2进制数,然后将其拆散放进set中,然后对输入的数进行对比。
这种时间复杂度最低,因为2的幂本来就没几个,然后进行对比的时候,挨个字符到set中找,只要找不到,或者长度对应不对,就直接返回false
这种方式很简单,这里就不写了
方法二:将当前传入数字转成字符数组,进行全排列,然后挨个进行判定
小tips:(n&(n-1))==0;//判断是不是为2的幂的小技巧
代码为方法二,主要是练下手,很久没写全排列了
class Solution {
private static boolean res;
public static boolean reorderedPowerOf2 ( int n) {
res = false ;
char [ ] ss = String . valueOf ( n) . toCharArray ( ) ;
rank ( ss, 0 ) ;
return res;
}
private static void rank ( char [ ] ss, int index) {
if ( res|| ss[ 0 ] == '0' ) return ;
if ( index>= ss. length) {
res = help ( ss) ;
return ;
}
Set < Character > set = new HashSet < > ( ) ;
for ( int i= index; i< ss. length; i++ ) {
if ( set. contains ( ss[ i] ) ) continue ;
swap ( ss, index, i) ;
rank ( ss, index+ 1 ) ;
swap ( ss, index, i) ;
set. add ( ss[ i] ) ;
}
}
private static void swap ( char [ ] ss, int i, int j) {
char t = ss[ i] ;
ss[ i] = ss[ j] ;
ss[ j] = t;
}
private static boolean help ( char [ ] ss) {
int n = Integer . valueOf ( new String ( ss) ) ;
return ( n& ( n- 1 ) ) == 0 ;
}
}
然后我又在评论区看到一个很厉害的评论,直接利用排序,就解决了比较是否2幂的问题,贴出来记录一下
public boolean reorderedPowerOf2 ( int N ) {
String [ ] rec = {
"1" , "2" , "4" , "8" , "16" , "23" , "46" , "128" , "256" , "125" , "0124" , "0248" , "0469" , "1289" , "13468" ,
"23678" , "35566" , "011237" , "122446" , "224588" , "0145678" , "0122579" , "0134449" , "0368888" ,
"11266777" , "23334455" , "01466788" , "112234778" , "234455668" , "012356789" , "0112344778" } ;
char [ ] at = String . valueOf ( N ) . toCharArray ( ) ;
Arrays . sort ( at) ;
String str = new String ( at) ;
for ( String p: rec) {
if ( str. equals ( p) ) return true ;
}
return false ;
}
10-30 lc260. 只出现一次的数字 III
这题也是剑指上的题
这种题都是要异或,然后异或的结果是两个目标值的异或值。
很明显,两个目标值不同,差异就在于二进制上,那么任选一个二进制来将两个目标值分到不同的部分,其他数也可以用这个二进制位来进行划分,从而问题变成了两个:从一个整数数组中,其中恰好只有一个元素出现一次,其他的都出现了两次, 选出目标值
class Solution {
public int [ ] singleNumber ( int [ ] nums) {
int sum = 0 ;
for ( int num: nums) sum ^= num;
int index = 0 ;
while ( ( ( 1 << index) & sum) == 0 ) index++ ;
int t = 0 ;
for ( int num: nums) if ( ( ( 1 << index) & num) == 0 ) t ^= num;
return new int [ ] {
t, sum^ t} ;
}
}