#1
#合并两个有序数组
#给你两个有序整数数组nums1和nums2,请你将nums2合并到nums1中,使nums1成为一个有序数组。
#初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。
#你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
输入:nums1 = [ 1 , 2 , 3 , 0 , 0 , 0 ] , m = 3 , nums2 = [ 2 , 5 , 6 ] , n = 3
输出:[ 1 , 2 , 2 , 3 , 5 , 6 ]
class Solution {
public void merge ( int [ ] nums1, int m, int [ ] nums2, int n) {
for ( int i = 0 ; i != n; ++ i) {
nums1[ m + i] = nums2[ i] ;
}
Arrays . sort ( nums1) ;
}
}
#2
#多数元素
#给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/ 2 ⌋ 的元素。
#你可以假设数组是非空的,并且给定的数组总是存在多数元素。
输入:[ 3 , 2 , 3 ]
输出:3
class Solution {
private Map < Integer , Integer > countNums ( int [ ] nums) {
Map < Integer , Integer > counts = new HashMap < Integer , Integer > ( ) ;
for ( int num : nums) {
if ( ! counts. containsKey ( num) ) {
counts. put ( num, 1 ) ;
} else {
counts. put ( num, counts. get ( num) + 1 ) ;
}
}
return counts;
}
public int majorityElement ( int [ ] nums) {
Map < Integer , Integer > counts = countNums ( nums) ;
Map. Entry < Integer , Integer > majorityEntry = null ;
for ( Map. Entry < Integer , Integer > entry : counts. entrySet ( ) ) {
if ( majorityEntry == null || entry. getValue ( ) > majorityEntry. getValue ( ) ) {
majorityEntry = entry;
}
}
return majorityEntry. getKey ( ) ;
}
}
#3
#存在重复元素
#给定一个整数数组,判断是否存在重复元素。
#如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
示例 1 :
输入: [ 1 , 2 , 3 , 1 ]
输出: true
示例 2 :
输入: [ 1 , 2 , 3 , 4 ]
输出: false
class Solution {
public boolean containsDuplicate ( int [ ] nums) {
Arrays . sort ( nums) ;
int n = nums. length;
for ( int i = 0 ; i < n - 1 ; i++ ) {
if ( nums[ i] == nums[ i + 1 ] ) {
return true ;
}
}
return false ;
}
}
class Solution {
public boolean containsDuplicate ( int [ ] nums) {
Set < Integer > set = new HashSet < Integer > ( ) ;
for ( int x : nums) {
if ( ! set. add ( x) ) {
return true ;
}
}
return false ;
}
}
#4
#有效的字母异位词
#给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
#注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1 :
输入: s = "anagram" , t = "nagaram"
输出: true
示例 2 :
输入: s = "rat" , t = "car"
输出: false
class Solution {
public boolean isAnagram ( String s, String t) {
if ( s. length ( ) != t. length ( ) ) {
return false ;
}
char [ ] str1 = s. toCharArray ( ) ;
char [ ] str2 = t. toCharArray ( ) ;
Arrays . sort ( str1) ;
Arrays . sort ( str2) ;
return Arrays . equals ( str1, str2) ;
}
}
class Solution {
public boolean isAnagram ( String s, String t) {
if ( s. length ( ) != t. length ( ) ) {
return false ;
}
int [ ] table = new int [ 26 ] ;
for ( int i = 0 ; i < s. length ( ) ; i++ ) {
table[ s. charAt ( i) - 'a' ] ++ ;
}
for ( int i = 0 ; i < t. length ( ) ; i++ ) {
table[ t. charAt ( i) - 'a' ] -- ;
if ( table[ t. charAt ( i) - 'a' ] < 0 ) {
return false ;
}
}
return true ;
}
}
class Solution {
public boolean isAnagram ( String s, String t) {
if ( s. length ( ) != t. length ( ) ) {
return false ;
}
Map < Character , Integer > table = new HashMap < Character , Integer > ( ) ;
for ( int i = 0 ; i < s. length ( ) ; i++ ) {
char ch = s. charAt ( i) ;
table. put ( ch, table. getOrDefault ( ch, 0 ) + 1 ) ;
}
for ( int i = 0 ; i < t. length ( ) ; i++ ) {
char ch = t. charAt ( i) ;
table. put ( ch, table. getOrDefault ( ch, 0 ) - 1 ) ;
if ( table. get ( ch) < 0 ) {
return false ;
}
}
return true ;
}
}
#5
#丢失的数字
#给定一个包含 [ 0 , n] 中 n 个数的数组 nums ,找出 [ 0 , n] 这个范围内没有出现在数组中的那个数。
示例 1 :
输入:nums = [ 3 , 0 , 1 ]
输出:2
解释:n = 3 ,因为有 3 个数字,所以所有的数字都在范围 [ 0 , 3 ] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 2 :
输入:nums = [ 0 , 1 ]
输出:2
解释:n = 2 ,因为有 2 个数字,所以所有的数字都在范围 [ 0 , 2 ] 内。2 是丢失的数字,因为它没有出现在 nums 中。
class Solution {
public int missingNumber ( int [ ] nums) {
Arrays . sort ( nums) ;
if ( nums[ nums. length- 1 ] != nums. length) {
return nums. length;
}
else if ( nums[ 0 ] != 0 ) {
return 0 ;
}
for ( int i = 1 ; i < nums. length; i++ ) {
int expectedNum = nums[ i- 1 ] + 1 ;
if ( nums[ i] != expectedNum) {
return expectedNum;
}
}
return - 1 ;
}
}
class Solution {
public int missingNumber ( int [ ] nums) {
Set < Integer > numSet = new HashSet < Integer > ( ) ;
for ( int num : nums) numSet. add ( num) ;
int expectedNumCount = nums. length + 1 ;
for ( int number = 0 ; number < expectedNumCount; number++ ) {
if ( ! numSet. contains ( number) ) {
return number;
}
}
return - 1 ;
}
}
class Solution {
public int missingNumber ( int [ ] nums) {
int missing = nums. length;
for ( int i = 0 ; i < nums. length; i++ ) {
missing ^= i ^ nums[ i] ;
}
return missing;
}
}
class Solution {
public int missingNumber ( int [ ] nums) {
int expectedSum = nums. length* ( nums. length + 1 ) / 2 ;
int actualSum = 0 ;
for ( int num : nums) actualSum += num;
return expectedSum - actualSum;
}
}
#6
#两个数组的交集
#给定两个数组,编写一个函数来计算它们的交集。
示例 1 :
输入:nums1 = [ 1 , 2 , 2 , 1 ] , nums2 = [ 2 , 2 ]
输出:[ 2 ]
示例 2 :
输入:nums1 = [ 4 , 9 , 5 ] , nums2 = [ 9 , 4 , 9 , 8 , 4 ]
输出:[ 9 , 4 ]
class Solution {
public int [ ] intersection ( int [ ] nums1, int [ ] nums2) {
Set < Integer > set1 = new HashSet < Integer > ( ) ;
Set < Integer > set2 = new HashSet < Integer > ( ) ;
for ( int num : nums1) {
set1. add ( num) ;
}
for ( int num : nums2) {
set2. add ( num) ;
}
return getIntersection ( set1, set2) ;
}
public int [ ] getIntersection ( Set < Integer > set1, Set < Integer > set2) {
if ( set1. size ( ) > set2. size ( ) ) {
return getIntersection ( set2, set1) ;
}
Set < Integer > intersectionSet = new HashSet < Integer > ( ) ;
for ( int num : set1) {
if ( set2. contains ( num) ) {
intersectionSet. add ( num) ;
}
}
int [ ] intersection = new int [ intersectionSet. size ( ) ] ;
int index = 0 ;
for ( int num : intersectionSet) {
intersection[ index++ ] = num;
}
return intersection;
}
}
class Solution {
public int [ ] intersection ( int [ ] nums1, int [ ] nums2) {
Arrays . sort ( nums1) ;
Arrays . sort ( nums2) ;
int length1 = nums1. length, length2 = nums2. length;
int [ ] intersection = new int [ length1 + length2] ;
int index = 0 , index1 = 0 , index2 = 0 ;
while ( index1 < length1 && index2 < length2) {
int num1 = nums1[ index1] , num2 = nums2[ index2] ;
if ( num1 == num2) {
if ( index == 0 || num1 != intersection[ index - 1 ] ) {
intersection[ index++ ] = num1;
}
index1++ ;
index2++ ;
} else if ( num1 < num2) {
index1++ ;
} else {
index2++ ;
}
}
return Arrays . copyOfRange ( intersection, 0 , index) ;
}
}
#7
#两个数组的交集 II
#给定两个数组,编写一个函数来计算它们的交集。
示例 1 :
输入:nums1 = [ 1 , 2 , 2 , 1 ] , nums2 = [ 2 , 2 ]
输出:[ 2 , 2 ]
示例 2 :
输入:nums1 = [ 4 , 9 , 5 ] , nums2 = [ 9 , 4 , 9 , 8 , 4 ]
输出:[ 4 , 9 ]
class Solution {
public int [ ] intersect ( int [ ] nums1, int [ ] nums2) {
if ( nums1. length > nums2. length) {
return intersect ( nums2, nums1) ;
}
Map < Integer , Integer > map = new HashMap < Integer , Integer > ( ) ;
for ( int num : nums1) {
int count = map. getOrDefault ( num, 0 ) + 1 ;
map. put ( num, count) ;
}
int [ ] intersection = new int [ nums1. length] ;
int index = 0 ;
for ( int num : nums2) {
int count = map. getOrDefault ( num, 0 ) ;
if ( count > 0 ) {
intersection[ index++ ] = num;
count-- ;
if ( count > 0 ) {
map. put ( num, count) ;
} else {
map. remove ( num) ;
}
}
}
return Arrays . copyOfRange ( intersection, 0 , index) ;
}
}
class Solution {
public int [ ] intersect ( int [ ] nums1, int [ ] nums2) {
Arrays . sort ( nums1) ;
Arrays . sort ( nums2) ;
int length1 = nums1. length, length2 = nums2. length;
int [ ] intersection = new int [ Math . min ( length1, length2) ] ;
int index1 = 0 , index2 = 0 , index = 0 ;
while ( index1 < length1 && index2 < length2) {
if ( nums1[ index1] < nums2[ index2] ) {
index1++ ;
} else if ( nums1[ index1] > nums2[ index2] ) {
index2++ ;
} else {
intersection[ index] = nums1[ index1] ;
index1++ ;
index2++ ;
index++ ;
}
}
return Arrays . copyOfRange ( intersection, 0 , index) ;
}
}
#8
#找不同
#给定两个字符串 s 和 t,它们只包含小写字母。
#字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
#请找出在 t 中被添加的字母。
示例 1 :
输入:s = "abcd" , t = "abcde"
输出:"e"
解释:'e' 是那个被添加的字母。
示例 2 :
输入:s = "" , t = "y"
输出:"y"
class Solution {
public char findTheDifference ( String s, String t) {
int [ ] cnt = new int [ 26 ] ;
for ( int i = 0 ; i < s. length ( ) ; ++ i) {
char ch = s. charAt ( i) ;
cnt[ ch - 'a' ] ++ ;
}
for ( int i = 0 ; i < t. length ( ) ; ++ i) {
char ch = t. charAt ( i) ;
cnt[ ch - 'a' ] -- ;
if ( cnt[ ch - 'a' ] < 0 ) {
return ch;
}
}
return ' ' ;
}
}
class Solution {
public char findTheDifference ( String s, String t) {
int as = 0 , at = 0 ;
for ( int i = 0 ; i < s. length ( ) ; ++ i) {
as += s. charAt ( i) ;
}
for ( int i = 0 ; i < t. length ( ) ; ++ i) {
at += t. charAt ( i) ;
}
return ( char ) ( at - as) ;
}
}
class Solution {
public char findTheDifference ( String s, String t) {
int ret = 0 ;
for ( int i = 0 ; i < s. length ( ) ; ++ i) {
ret ^= s. charAt ( i) ;
}
for ( int i = 0 ; i < t. length ( ) ; ++ i) {
ret ^= t. charAt ( i) ;
}
return ( char ) ret;
}
}
#9
#第三大的数
#给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。
示例 1 :
输入:[ 3 , 2 , 1 ]
输出:1
解释:第三大的数是 1 。
示例 2 :
输入:[ 1 , 2 ]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。
public int thirdMax ( int [ ] nums) {
Arrays . sort ( nums) ;
List < Integer > ans = new ArrayList < > ( ) ;
for ( int i: nums) {
if ( ans. contains ( i) ) {
continue ;
}
ans. add ( i) ;
}
int n = ans. size ( ) ;
if ( n== 1 || n== 2 ) {
return ans. get ( n- 1 ) ;
}
return ans. get ( ans. size ( ) - 3 ) ;
}
#10
#分发饼干
#假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
#对每个孩子 i,都有一个胃口值 g[ i] ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干j,
#都有一个尺寸 s[ j] 。如果 s[ j] >= g[ i] ,我们#可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。
#你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
class Solution {
public int findContentChildren ( int [ ] g, int [ ] s) {
Arrays . sort ( g) ;
Arrays . sort ( s) ;
int numOfChildren = g. length, numOfCookies = s. length;
int count = 0 ;
for ( int i = 0 , j = 0 ; i < numOfChildren && j < numOfCookies; i++ , j++ ) {
while ( j < numOfCookies && g[ i] > s[ j] ) {
j++ ;
}
if ( j < numOfCookies) {
count++ ;
}
}
return count;
}
}
#11
#相对名次
#给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌。前三名运动员将会被分别授予
# “金牌”,“银牌” 和“ 铜牌”("Gold Medal" , "Silver Medal" , "Bronze Medal" )。
#( 注:分数越高的选手,排名越靠前。)
输入: [ 5 , 4 , 3 , 2 , 1 ]
输出: [ "Gold Medal" , "Silver Medal" , "Bronze Medal" , "4" , "5" ]
解释: 前三名运动员的成绩为前三高的,因此将会分别被授予 “金牌”,“银牌”和“铜牌” ( "Gold Medal" , "Silver Medal" and "Bronze Medal" ) .
余下的两名运动员,我们只需要通过他们的成绩计算将其相对名次即可。
提示:
N 是一个正整数并且不会超过 10000 。
所有运动员的成绩都不相同。
class Solution {
public String [ ] findRelativeRanks ( int [ ] score) {
Map < Integer , Integer > map= new TreeMap < > ( Comparator . reverseOrder ( ) ) ;
String [ ] result= new String [ score. length] ;
for ( int i= 0 ; i< score. length; i++ ) {
map. put ( score[ i] , i) ;
}
int rank= 1 ;
Iterator < Map. Entry < Integer , Integer > > iterator= map. entrySet ( ) . iterator ( ) ;
while ( iterator. hasNext ( ) ) {
Map. Entry < Integer , Integer > entry= iterator. next ( ) ;
if ( rank== 1 ) result[ entry. getValue ( ) ] = "Gold Medal" ;
else if ( rank== 2 ) result[ entry. getValue ( ) ] = "Silver Medal" ;
else if ( rank== 3 ) result[ entry. getValue ( ) ] = "Bronze Medal" ;
else result[ entry. getValue ( ) ] = String . valueOf ( rank) ;
rank++ ;
}
return result;
}
}
#12
#数组拆分
#给定长度为 2 n 的整数数组 nums ,你的任务是将这些数分成 n 对,
#例如 ( a1, b1) , ( a2, b2) , . . . , ( an, bn) ,使得从 1 到 n 的 min ( ai, bi) 总和最大。
返回该 最大总和 。
示例 1 :
输入:nums = [ 1 , 4 , 3 , 2 ]
输出:4
解释:所有可能的分法(忽略元素顺序)为:
1. ( 1 , 4 ) , ( 2 , 3 ) -> min ( 1 , 4 ) + min ( 2 , 3 ) = 1 + 2 = 3
2. ( 1 , 3 ) , ( 2 , 4 ) -> min ( 1 , 3 ) + min ( 2 , 4 ) = 1 + 2 = 3
3. ( 1 , 2 ) , ( 3 , 4 ) -> min ( 1 , 2 ) + min ( 3 , 4 ) = 1 + 3 = 4
所以最大总和为 4
示例 2 :
输入:nums = [ 6 , 2 , 6 , 5 , 1 , 2 ]
输出:9
解释:最优的分法为 ( 2 , 1 ) , ( 2 , 5 ) , ( 6 , 6 ) . min ( 2 , 1 ) + min ( 2 , 5 ) + min ( 6 , 6 ) = 1 + 2 + 6 = 9
class Solution {
public int arrayPairSum ( int [ ] nums) {
Arrays . sort ( nums) ;
int ans = 0 ;
for ( int i = 0 ; i < nums. length; i += 2 ) {
ans += nums[ i] ;
}
return ans;
}
}
#13
#最长和谐子序列
#和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。
#现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。
#数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。
示例 1 :
输入:nums = [ 1 , 3 , 2 , 2 , 5 , 2 , 3 , 7 ]
输出:5
解释:最长的和谐子序列是 [ 3 , 2 , 2 , 2 , 3 ]
示例 2 :
输入:nums = [ 1 , 2 , 3 , 4 ]
输出:2
public class Solution {
public int findLHS ( int [ ] nums) {
int res = 0 ;
for ( int i = 0 ; i < nums. length; i++ ) {
int count = 0 ;
boolean flag = false ;
for ( int j = 0 ; j < nums. length; j++ ) {
if ( nums[ j] == nums[ i] )
count++ ;
else if ( nums[ j] + 1 == nums[ i] ) {
count++ ;
flag = true ;
}
}
if ( flag)
res = Math . max ( count, res) ;
}
return res;
}
}
public class Solution {
public int findLHS ( int [ ] nums) {
HashMap < Integer , Integer > map = new HashMap < > ( ) ;
int res = 0 ;
for ( int num: nums) {
map. put ( num, map. getOrDefault ( num, 0 ) + 1 ) ;
}
for ( int key: map. keySet ( ) ) {
if ( map. containsKey ( key + 1 ) )
res = Math . max ( res, map. get ( key) + map. get ( key + 1 ) ) ;
}
return res;
}
}
public class Solution {
public int findLHS ( int [ ] nums) {
HashMap < Integer , Integer > map = new HashMap < > ( ) ;
int res = 0 ;
for ( int num: nums) {
map. put ( num, map. getOrDefault ( num, 0 ) + 1 ) ;
if ( map. containsKey ( num + 1 ) )
res = Math . max ( res, map. get ( num) + map. get ( num + 1 ) ) ;
if ( map. containsKey ( num - 1 ) )
res = Math . max ( res, map. get ( num) + map. get ( num - 1 ) ) ;
}
return res;
}
}
#14
#三个数的最大乘积
#给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例 1 :
输入:nums = [ 1 , 2 , 3 ]
输出:6
示例 2 :
输入:nums = [ 1 , 2 , 3 , 4 ]
输出:24
class Solution {
public int maximumProduct ( int [ ] nums) {
Arrays . sort ( nums) ;
int n = nums. length;
return Math . max ( nums[ 0 ] * nums[ 1 ] * nums[ n - 1 ] , nums[ n - 3 ] * nums[ n - 2 ] * nums[ n - 1 ] ) ;
}
}
class Solution {
public int maximumProduct ( int [ ] nums) {
int min1 = Integer . MAX_VALUE, min2 = Integer . MAX_VALUE;
int max1 = Integer . MIN_VALUE, max2 = Integer . MIN_VALUE, max3 = Integer . MIN_VALUE;
for ( int x : nums) {
if ( x < min1) {
min2 = min1;
min1 = x;
} else if ( x < min2) {
min2 = x;
}
if ( x > max1) {
max3 = max2;
max2 = max1;
max1 = x;
} else if ( x > max2) {
max3 = max2;
max2 = x;
} else if ( x > max3) {
max3 = x;
}
}
return Math . max ( min1 * min2 * max1, max1 * max2 * max3) ;
}
}
#15
#错误的集合
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1 :
输入:nums = [ 1 , 2 , 2 , 4 ]
输出:[ 2 , 3 ]
示例 2 :
输入:nums = [ 1 , 1 ]
输出:[ 1 , 2 ]
class Solution {
public int [ ] findErrorNums ( int [ ] nums) {
int [ ] errorNums = new int [ 2 ] ;
int n = nums. length;
Arrays . sort ( nums) ;
int prev = 0 ;
for ( int i = 0 ; i < n; i++ ) {
int curr = nums[ i] ;
if ( curr == prev) {
errorNums[ 0 ] = prev;
} else if ( curr - prev > 1 ) {
errorNums[ 1 ] = prev + 1 ;
}
prev = curr;
}
if ( nums[ n - 1 ] != n) {
errorNums[ 1 ] = n;
}
return errorNums;
}
}
class Solution {
public int [ ] findErrorNums ( int [ ] nums) {
int [ ] errorNums = new int [ 2 ] ;
int n = nums. length;
Map < Integer , Integer > map = new HashMap < Integer , Integer > ( ) ;
for ( int num : nums) {
map. put ( num, map. getOrDefault ( num, 0 ) + 1 ) ;
}
for ( int i = 1 ; i <= n; i++ ) {
int count = map. getOrDefault ( i, 0 ) ;
if ( count == 2 ) {
errorNums[ 0 ] = i;
} else if ( count == 0 ) {
errorNums[ 1 ] = i;
}
}
return errorNums;
}
}
class Solution {
public int [ ] findErrorNums ( int [ ] nums) {
int n = nums. length;
int xor = 0 ;
for ( int num : nums) {
xor ^= num;
}
for ( int i = 1 ; i <= n; i++ ) {
xor ^= i;
}
int lowbit = xor & ( - xor) ;
int num1 = 0 , num2 = 0 ;
for ( int num : nums) {
if ( ( num & lowbit) == 0 ) {
num1 ^= num;
} else {
num2 ^= num;
}
}
for ( int i = 1 ; i <= n; i++ ) {
if ( ( i & lowbit) == 0 ) {
num1 ^= i;
} else {
num2 ^= i;
}
}
for ( int num : nums) {
if ( num == num1) {
return new int [ ] { num1, num2} ;
}
}
return new int [ ] { num2, num1} ;
}
}
#16
#词典中最长的单词
#给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,
#该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。
#若无答案,则返回空字符串。
class Solution {
public String longestWord ( String [ ] words) {
String ans = "" ;
Set < String > wordset = new HashSet ( ) ;
for ( String word: words) wordset. add ( word) ;
for ( String word: words) {
if ( word. length ( ) > ans. length ( ) ||
word. length ( ) == ans. length ( ) && word. compareTo ( ans) < 0 ) {
boolean good = true ;
for ( int k = 1 ; k < word. length ( ) ; ++ k) {
if ( ! wordset. contains ( word. substring ( 0 , k) ) ) {
good = false ;
break ;
}
}
if ( good) ans = word;
}
}
return ans;
}
}
class Solution {
public String longestWord ( String [ ] words) {
Set < String > wordset = new HashSet ( ) ;
for ( String word: words) wordset. add ( word) ;
Arrays . sort ( words, ( a, b) -> a. length ( ) == b. length ( )
? a. compareTo ( b) : b. length ( ) - a. length ( ) ) ;
for ( String word: words) {
boolean good = true ;
for ( int k = 1 ; k < word. length ( ) ; ++ k) {
if ( ! wordset. contains ( word. substring ( 0 , k) ) ) {
good = false ;
break ;
}
}
if ( good) return word;
}
return "" ;
}
}
class Solution {
public String longestWord ( String [ ] words) {
Trie trie = new Trie ( ) ;
int index = 0 ;
for ( String word: words) {
trie. insert ( word, ++ index) ;
}
trie. words = words;
return trie. dfs ( ) ;
}
}
class Node {
char c;
HashMap < Character , Node > children = new HashMap ( ) ;
int end;
public Node ( char c) {
this . c = c;
}
}
class Trie {
Node root;
String [ ] words;
public Trie ( ) {
root = new Node ( '0' ) ;
}
public void insert ( String word, int index) {
Node cur = root;
for ( char c: word. toCharArray ( ) ) {
cur. children. putIfAbsent ( c, new Node ( c) ) ;
cur = cur. children. get ( c) ;
}
cur. end = index;
}
public String dfs ( ) {
String ans = "" ;
Stack < Node > stack = new Stack ( ) ;
stack. push ( root) ;
while ( ! stack. empty ( ) ) {
Node node = stack. pop ( ) ;
if ( node. end > 0 || node == root) {
if ( node != root) {
String word = words[ node. end - 1 ] ;
if ( word. length ( ) > ans. length ( ) ||
word. length ( ) == ans. length ( ) && word. compareTo ( ans) < 0 ) {
ans = word;
}
}
for ( Node nei: node. children. values ( ) ) {
stack. push ( nei) ;
}
}
}
return ans;
}
}
#17
#至少是其他数字两倍的最大数
#给你一个整数数组 nums ,其中总是存在 唯一的 一个最大整数 。
#请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 。
#如果是,则返回 最大元素的下标 ,否则返回 - 1 。
示例 1 :
输入:nums = [ 3 , 6 , 1 , 0 ]
输出:1
解释:6 是最大的整数,对于数组中的其他整数,6 大于数组中其他元素的两倍。6 的下标是 1 ,所以返回 1 。
示例 2 :
输入:nums = [ 1 , 2 , 3 , 4 ]
输出:- 1
解释:4 没有超过 3 的两倍大,所以返回 - 1 。
class Solution {
public int dominantIndex ( int [ ] nums) {
int maxIndex = 0 ;
for ( int i = 0 ; i < nums. length; ++ i) {
if ( nums[ i] > nums[ maxIndex] )
maxIndex = i;
}
for ( int i = 0 ; i < nums. length; ++ i) {
if ( maxIndex != i && nums[ maxIndex] < 2 * nums[ i] )
return - 1 ;
}
return maxIndex;
}
}
#18
#公平的糖果交换
#爱丽丝和鲍勃有不同大小的糖果棒:A [ i] 是爱丽丝拥有的第 i 根糖果棒的大小,B [ j] 是鲍勃拥有的第 j 根糖果棒的大小。
因为他们是朋友,所以他们想交换一根糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。)
返回一个整数数组 ans,其中 ans[ 0 ] 是爱丽丝必须交换的糖果棒的大小,ans[ 1 ] 是 Bob 必须交换的糖果棒的大小。
如果有多个答案,你可以返回其中任何一个。保证答案存在。
class Solution {
public int [ ] fairCandySwap ( int [ ] aliceSizes, int [ ] bobSizes) {
int sumA = Arrays . stream ( aliceSizes) . sum ( ) ;
int sumB = Arrays . stream ( bobSizes) . sum ( ) ;
int delta = ( sumA - sumB) / 2 ;
Set < Integer > rec = new HashSet < Integer > ( ) ;
for ( int num : aliceSizes) {
rec. add ( num) ;
}
int [ ] ans = new int [ 2 ] ;
for ( int y : bobSizes) {
int x = y + delta;
if ( rec. contains ( x) ) {
ans[ 0 ] = x;
ans[ 1 ] = y;
break ;
}
}
return ans;
}
}
#19
#按奇偶排序数组
给定一个非负整数数组 A ,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。
你可以返回满足此条件的任何数组作为答案。
class Solution {
public int [ ] sortArrayByParity ( int [ ] A ) {
Integer [ ] B = new Integer [ A . length] ;
for ( int t = 0 ; t < A . length; ++ t)
B [ t] = A [ t] ;
Arrays . sort ( B , ( a, b) -> Integer . compare ( a% 2 , b% 2 ) ) ;
for ( int t = 0 ; t < A . length; ++ t)
A [ t] = B [ t] ;
return A ;
}
}
class Solution {
public int [ ] sortArrayByParity ( int [ ] A ) {
int [ ] ans = new int [ A . length] ;
int t = 0 ;
for ( int i = 0 ; i < A . length; ++ i)
if ( A [ i] % 2 == 0 )
ans[ t++ ] = A [ i] ;
for ( int i = 0 ; i < A . length; ++ i)
if ( A [ i] % 2 == 1 )
ans[ t++ ] = A [ i] ;
return ans;
}
}
class Solution {
public int [ ] sortArrayByParity ( int [ ] A ) {
int i = 0 , j = A . length - 1 ;
while ( i < j) {
if ( A [ i] % 2 > A [ j] % 2 ) {
int tmp = A [ i] ;
A [ i] = A [ j] ;
A [ j] = tmp;
}
if ( A [ i] % 2 == 0 ) i++ ;
if ( A [ j] % 2 == 1 ) j-- ;
}
return A ;
}
}
#20
#按奇偶排序数组
#给定一个非负整数数组 A , A 中一半整数是奇数,一半整数是偶数。
#对数组进行排序,以便当 A [ i] 为奇数时,i 也是奇数;当 A [ i] 为偶数时, i 也是偶数。
#你可以返回任何满足上述条件的数组作为答案。
示例:
输入:[ 4 , 2 , 5 , 7 ]
输出:[ 4 , 5 , 2 , 7 ]
解释:[ 4 , 7 , 2 , 5 ] ,[ 2 , 5 , 4 , 7 ] ,[ 2 , 7 , 4 , 5 ] 也会被接受。
class Solution {
public int [ ] sortArrayByParityII ( int [ ] A ) {
int n = A . length;
int [ ] ans = new int [ n] ;
int i = 0 ;
for ( int x : A ) {
if ( x % 2 == 0 ) {
ans[ i] = x;
i += 2 ;
}
}
i = 1 ;
for ( int x : A ) {
if ( x % 2 == 1 ) {
ans[ i] = x;
i += 2 ;
}
}
return ans;
}
}
class Solution {
public int [ ] sortArrayByParityII ( int [ ] A ) {
int n = A . length;
int j = 1 ;
for ( int i = 0 ; i < n; i += 2 ) {
if ( A [ i] % 2 == 1 ) {
while ( A [ j] % 2 == 1 ) {
j += 2 ;
}
swap ( A , i, j) ;
}
}
return A ;
}
public void swap ( int [ ] A , int i, int j) {
int temp = A [ i] ;
A [ i] = A [ j] ;
A [ j] = temp;
}
}
#21
#重新排列日志文件
给你一个日志数组 logs。每条日志都是以空格分隔的字串,其第一个字为字母与数字混合的 标识符 。
有两种不同类型的日志:
字母日志:除标识符之外,所有字均由小写字母组成
数字日志:除标识符之外,所有字均由数字组成
请按下述规则将日志重新排序:
所有 字母日志 都排在 数字日志 之前。
字母日志 在内容不同时,忽略标识符后,按内容字母顺序排序;在内容相同时,按标识符排序。
数字日志 应该保留原来的相对顺序。
返回日志的最终顺序。
示例 1 :
输入:logs = [ "dig1 8 1 5 1" , "let1 art can" , "dig2 3 6" , "let2 own kit dig" , "let3 art zero" ]
输出:[ "let1 art can" , "let3 art zero" , "let2 own kit dig" , "dig1 8 1 5 1" , "dig2 3 6" ]
解释:
字母日志的内容都不同,所以顺序为 "art can" , "art zero" , "own kit dig" 。
数字日志保留原来的相对顺序 "dig1 8 1 5 1" , "dig2 3 6" 。
示例 2 :
输入:logs = [ "a1 9 2 3 1" , "g1 act car" , "zo4 4 7" , "ab1 off key dog" , "a8 act zoo" ]
输出:[ "g1 act car" , "a8 act zoo" , "ab1 off key dog" , "a1 9 2 3 1" , "zo4 4 7" ]
class Solution {
public String [ ] reorderLogFiles ( String [ ] logs) {
Arrays . sort ( logs, ( log1, log2) -> {
String [ ] split1 = log1. split ( " " , 2 ) ;
String [ ] split2 = log2. split ( " " , 2 ) ;
boolean isDigit1 = Character . isDigit ( split1[ 1 ] . charAt ( 0 ) ) ;
boolean isDigit2 = Character . isDigit ( split2[ 1 ] . charAt ( 0 ) ) ;
if ( ! isDigit1 && ! isDigit2) {
int cmp = split1[ 1 ] . compareTo ( split2[ 1 ] ) ;
if ( cmp != 0 ) return cmp;
return split1[ 0 ] . compareTo ( split2[ 0 ] ) ;
}
return isDigit1 ? ( isDigit2 ? 0 : 1 ) : - 1 ;
} ) ;
return logs;
}
}
#22
#三角形的最大周长
给定由一些正数(代表长度)组成的数组 A ,返回由其中三个长度组成的、面积不为零的三角形的最大周长。
如果不能形成任何面积不为零的三角形,返回 0 。
示例 1 :
输入:[ 2 , 1 , 2 ]
输出:5
示例 2 :
输入:[ 1 , 2 , 1 ]
输出:0
示例 3 :
输入:[ 3 , 2 , 3 , 4 ]
输出:10
示例 4 :
输入:[ 3 , 6 , 2 , 3 ]
输出:8
class Solution {
public int largestPerimeter ( int [ ] A ) {
Arrays . sort ( A ) ;
for ( int i = A . length - 1 ; i >= 2 ; -- i) {
if ( A [ i - 2 ] + A [ i - 1 ] > A [ i] ) {
return A [ i - 2 ] + A [ i - 1 ] + A [ i] ;
}
}
return 0 ;
}
}
#23
#有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1 :
输入:nums = [ - 4 , - 1 , 0 , 3 , 10 ]
输出:[ 0 , 1 , 9 , 16 , 100 ]
解释:平方后,数组变为 [ 16 , 1 , 0 , 9 , 100 ]
排序后,数组变为 [ 0 , 1 , 9 , 16 , 100 ]
示例 2 :
输入:nums = [ - 7 , - 3 , 2 , 3 , 11 ]
输出:[ 4 , 9 , 9 , 49 , 121 ]
class Solution {
public int [ ] sortedSquares ( int [ ] nums) {
int [ ] ans = new int [ nums. length] ;
for ( int i = 0 ; i < nums. length; ++ i) {
ans[ i] = nums[ i] * nums[ i] ;
}
Arrays . sort ( ans) ;
return ans;
}
}
#24
# K 次取反后最大化的数组和
给定一个整数数组 A ,我们只能用以下方法修改该数组:我们选择某个索引 i 并将 A [ i] 替换为 - A [ i] ,然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)
以这种方式修改数组后,返回数组可能的最大和。
示例 1 :
输入:A = [ 4 , 2 , 3 ] , K = 1
输出:5
解释:选择索引 ( 1 , ) ,然后 A 变为 [ 4 , - 2 , 3 ] 。
示例 2 :
输入:A = [ 3 , - 1 , 0 , 2 ] , K = 3
输出:6
解释:选择索引 ( 1 , 2 , 2 ) ,然后 A 变为 [ 3 , 1 , 0 , 2 ] 。
class Solution {
public int largestSumAfterKNegations ( int [ ] A , int K ) {
int [ ] number = new int [ 201 ] ;
for ( int t : A ) {
number[ t + 100 ] ++ ;
}
int i = 0 ;
while ( K > 0 ) {
while ( number[ i] == 0 )
i++ ;
number[ i] -- ;
number[ 200 - i] ++ ;
if ( i > 100 ) {
i = 200 - i;
}
K -- ;
}
int sum = 0 ;
for ( int j = i; j < number. length ; j++ ) {
sum += ( j- 100 ) * number[ j] ;
}
return sum;
}
}
#25
#距离顺序排列矩阵单元格
给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 ( r, c) ,满足 0 <= r < R 且 0 <= c < C 。
另外,我们在该矩阵中给出了一个坐标为 ( r0, c0) 的单元格。
返回矩阵中的所有单元格的坐标,并按到 ( r0, c0) 的距离从最小到最大的顺序排,其中,两单元格( r1, c1) 和 ( r2, c2) 之间的距离是曼哈顿距离,| r1 - r2| + | c1 - c2| 。(你可以按任何满足此条件的顺序返回答案。)
示例 1 :
输入:R = 1 , C = 2 , r0 = 0 , c0 = 0
输出:[ [ 0 , 0 ] , [ 0 , 1 ] ]
解释:从 ( r0, c0) 到其他单元格的距离为:[ 0 , 1 ]
示例 2 :
输入:R = 2 , C = 2 , r0 = 0 , c0 = 1
输出:[ [ 0 , 1 ] , [ 0 , 0 ] , [ 1 , 1 ] , [ 1 , 0 ] ]
解释:从 ( r0, c0) 到其他单元格的距离为:[ 0 , 1 , 1 , 2 ]
[ [ 0 , 1 ] , [ 1 , 1 ] , [ 0 , 0 ] , [ 1 , 0 ] ] 也会被视作正确答案。
示例 3 :
输入:R = 2 , C = 3 , r0 = 1 , c0 = 2
输出:[ [ 1 , 2 ] , [ 0 , 2 ] , [ 1 , 1 ] , [ 0 , 1 ] , [ 1 , 0 ] , [ 0 , 0 ] ]
解释:从 ( r0, c0) 到其他单元格的距离为:[ 0 , 1 , 1 , 2 , 2 , 3 ]
其他满足题目要求的答案也会被视为正确,例如 [ [ 1 , 2 ] , [ 1 , 1 ] , [ 0 , 2 ] , [ 1 , 0 ] , [ 0 , 1 ] , [ 0 , 0 ] ] 。
class Solution {
public int [ ] [ ] allCellsDistOrder ( int rows, int cols, int rCenter, int cCenter) {
int [ ] [ ] ret = new int [ rows * cols] [ ] ;
for ( int i = 0 ; i < rows; i++ ) {
for ( int j = 0 ; j < cols; j++ ) {
ret[ i * cols + j] = new int [ ] { i, j} ;
}
}
Arrays . sort ( ret, new Comparator < int [ ] > ( ) {
public int compare ( int [ ] a, int [ ] b) {
return ( Math . abs ( a[ 0 ] - rCenter) + Math . abs ( a[ 1 ] - cCenter) ) - ( Math . abs ( b[ 0 ] - rCenter) + Math . abs ( b[ 1 ] - cCenter) ) ;
}
} ) ;
return ret;
}
}
class Solution {
public int [ ] [ ] allCellsDistOrder ( int rows, int cols, int rCenter, int cCenter) {
int maxDist = Math . max ( rCenter, rows - 1 - rCenter) + Math . max ( cCenter, cols - 1 - cCenter) ;
List < List < int [ ] >> bucket = new ArrayList < List < int [ ] >> ( ) ;
for ( int i = 0 ; i <= maxDist; i++ ) {
bucket. add ( new ArrayList < int [ ] > ( ) ) ;
}
for ( int i = 0 ; i < rows; i++ ) {
for ( int j = 0 ; j < cols; j++ ) {
int d = dist ( i, j, rCenter, cCenter) ;
bucket. get ( d) . add ( new int [ ] { i, j} ) ;
}
}
int [ ] [ ] ret = new int [ rows * cols] [ ] ;
int index = 0 ;
for ( int i = 0 ; i <= maxDist; i++ ) {
for ( int [ ] it : bucket. get ( i) ) {
ret[ index++ ] = it;
}
}
return ret;
}
public int dist ( int r1, int c1, int r2, int c2) {
return Math . abs ( r1 - r2) + Math . abs ( c1 - c2) ;
}
}
class Solution {
int [ ] dr = { 1 , 1 , - 1 , - 1 } ;
int [ ] dc = { 1 , - 1 , - 1 , 1 } ;
public int [ ] [ ] allCellsDistOrder ( int rows, int cols, int rCenter, int cCenter) {
int maxDist = Math . max ( rCenter, rows - 1 - rCenter) + Math . max ( cCenter, cols - 1 - cCenter) ;
int [ ] [ ] ret = new int [ rows * cols] [ ] ;
int row = rCenter, col = cCenter;
int index = 0 ;
ret[ index++ ] = new int [ ] { row, col} ;
for ( int dist = 1 ; dist <= maxDist; dist++ ) {
row-- ;
for ( int i = 0 ; i < 4 ; i++ ) {
while ( ( i % 2 == 0 && row != rCenter) || ( i % 2 != 0 && col != cCenter) ) {
if ( row >= 0 && row < rows & & col > = 0 && col < cols) {
ret[ index++ ] = new int [ ] { row, col} ;
}
row += dr[ i] ;
col += dc[ i] ;
}
}
}
return ret;
}
}
#26
#高度检查器
学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列。
请你返回能让所有学生以 非递减 高度排列的最小必要移动人数。
注意,当一组学生被选中时,他们之间可以以任何可能的方式重新排序,而未被选中的学生应该保持不动。
示例:
输入:heights = [ 1 , 1 , 4 , 2 , 1 , 3 ]
输出:3
解释:
当前数组:[ 1 , 1 , 4 , 2 , 1 , 3 ]
目标数组:[ 1 , 1 , 1 , 2 , 3 , 4 ]
在下标 2 处(从 0 开始计数)出现 4 vs 1 ,所以我们必须移动这名学生。
在下标 4 处(从 0 开始计数)出现 1 vs 3 ,所以我们必须移动这名学生。
在下标 5 处(从 0 开始计数)出现 3 vs 4 ,所以我们必须移动这名学生。
示例 2 :
输入:heights = [ 5 , 1 , 2 , 3 , 4 ]
输出:5
class Solution {
public int heightChecker ( int [ ] heights) {
int [ ] nums = new int [ heights. length] ;
for ( int i = 0 ; i < heights. length; i++ ) {
nums[ i] = heights[ i] ;
}
Arrays . sort ( nums) ;
int count = 0 ;
for ( int j = 0 ; j < nums. length; j++ ) {
if ( nums[ j] != heights[ j] )
count++ ;
}
return count;
}
}
#27
1122. 数组的相对排序
给你两个数组,arr1 和 arr2,
arr2 中的元素各不相同
arr2 中的每个元素都出现在 arr1 中
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。
示例:
输入:arr1 = [ 2 , 3 , 1 , 3 , 2 , 4 , 6 , 7 , 9 , 2 , 19 ] , arr2 = [ 2 , 1 , 4 , 3 , 9 , 6 ]
输出:[ 2 , 2 , 2 , 1 , 4 , 3 , 3 , 9 , 6 , 7 , 19 ]
class Solution {
public int [ ] relativeSortArray ( int [ ] arr1, int [ ] arr2) {
int upper = 0 ;
for ( int x : arr1) {
upper = Math . max ( upper, x) ;
}
int [ ] frequency = new int [ upper + 1 ] ;
for ( int x : arr1) {
++ frequency[ x] ;
}
int [ ] ans = new int [ arr1. length] ;
int index = 0 ;
for ( int x : arr2) {
for ( int i = 0 ; i < frequency[ x] ; ++ i) {
ans[ index++ ] = x;
}
frequency[ x] = 0 ;
}
for ( int x = 0 ; x <= upper; ++ x) {
for ( int i = 0 ; i < frequency[ x] ; ++ i) {
ans[ index++ ] = x;
}
}
return ans;
}
}
#28
#最小绝对差
给你个整数数组 arr,其中每个元素都 不相同。
请你找到所有具有最小绝对差的元素对,并且按升序的顺序返回。
示例 1 :
输入:arr = [ 4 , 2 , 1 , 3 ]
输出:[ [ 1 , 2 ] , [ 2 , 3 ] , [ 3 , 4 ] ]
示例 2 :
输入:arr = [ 1 , 3 , 6 , 10 , 15 ]
输出:[ [ 1 , 3 ] ]
示例 3 :
输入:arr = [ 3 , 8 , - 10 , 23 , 19 , - 4 , - 14 , 27 ]
输出:[ [ - 14 , - 10 ] , [ 19 , 23 ] , [ 23 , 27 ] ]
class Solution {
public List < List < Integer > > minimumAbsDifference ( int [ ] arr) {
List < List < Integer > > absNumbers = new ArrayList < > ( ) ;
int [ ] differences = new int [ arr. length] ;
int [ ] array = new int [ arr. length + 1 ] ;
Arrays . sort ( arr) ;
for ( int i = 0 ; i < arr. length; i++ ) {
array[ i] = arr[ i] ;
}
array[ arr. length] = arr[ 0 ] ;
for ( int i = 0 ; i < arr. length; i++ ) {
differences[ i] = Math . abs ( array[ i] - array[ i + 1 ] ) ;
}
int min = Integer . MAX_VALUE;
for ( int i = 0 ; i < differences. length; i++ ) {
if ( differences[ i] < min) {
min = differences[ i] ;
}
}
for ( int i = 0 ; i < differences. length; i++ ) {
if ( min == differences[ i] ) {
List < Integer > temp = new ArrayList < > ( ) ;
temp. add ( array[ i] ) ;
temp. add ( array[ i + 1 ] ) ;
absNumbers. add ( temp) ;
}
}
return absNumbers;
}
}
#29
#数组序号转换
给你一个整数数组 arr ,请你将数组中的每个元素替换为它们排序后的序号。
序号代表了一个元素有多大。序号编号的规则如下:
序号从 1 开始编号。
一个元素越大,那么序号越大。如果两个元素相等,那么它们的序号相同。
每个数字的序号都应该尽可能地小。
示例 1 :
输入:arr = [ 40 , 10 , 20 , 30 ]
输出:[ 4 , 1 , 2 , 3 ]
解释:40 是最大的元素。 10 是最小的元素。 20 是第二小的数字。 30 是第三小的数字。
示例 2 :
输入:arr = [ 100 , 100 , 100 ]
输出:[ 1 , 1 , 1 ]
解释:所有元素有相同的序号。
class Solution {
public int [ ] arrayRankTransform ( int [ ] arr) {
int min = Integer . MAX_VALUE, max = Integer . MIN_VALUE;
for ( int num : arr) {
if ( num < min) min = num;
if ( num > max) max = num;
}
int [ ] count = new int [ max - min + 1 ] ;
for ( int num : arr)
count[ num - min] = 1 ;
int [ ] preSum = new int [ count. length + 1 ] ;
for ( int i = 1 ; i < preSum. length; i++ )
preSum[ i] = preSum[ i - 1 ] + count[ i - 1 ] ;
int [ ] ans = new int [ arr. length] ;
int index = 0 ;
for ( int num : arr)
ans[ index++ ] = preSum[ num - min] + 1 ;
return ans;
}
}
在这里插入代码片