1. 322【零钱兑换】- 动态规划
题目: 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的。代码:
class Solution {
public int coinChange ( int [ ] coins, int amount) {
if ( amount== 0 ) return 0 ;
int [ ] dp = new int [ amount+ 1 ] ;
Arrays . fill ( dp, amount+ 1 ) ;
dp[ 0 ] = 0 ;
for ( int i= 0 ; i< coins. length; i++ ) {
for ( int j= 1 ; j<= amount; j++ ) {
if ( coins[ i] <= j) {
dp[ j] = Math . min ( dp[ j] , dp[ j- coins[ i] ] + 1 ) ;
}
}
}
return dp[ amount] > amount? - 1 : dp[ amount] ;
}
}
2. 33【搜索旋转排序数组】- 二分查找
题目: 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。 你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。代码:
class Solution {
public int search ( int [ ] nums, int target) {
if ( nums. length == 1 ) return nums[ 0 ] == target? 0 : - 1 ;
int left = 0 ;
int right = nums. length- 1 ;
while ( left<= right) {
int mid = left+ ( right- left) / 2 ;
if ( nums[ mid] == target) return mid;
if ( nums[ 0 ] <= nums[ mid] ) {
if ( nums[ mid] > target && nums[ 0 ] <= target) {
right = mid - 1 ;
} else {
left = mid + 1 ;
}
} else {
if ( nums[ mid] < target && nums[ nums. length- 1 ] >= target) {
left = mid+ 1 ;
} else {
right = mid- 1 ;
}
}
}
return - 1 ;
}
}
3. 215【数组中的第k个最大元素】- 优先级队列
题目: 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。代码:
class Solution {
public int findKthLargest ( int [ ] nums, int k) {
PriorityQueue < Integer > heap = new PriorityQueue < > ( new Comparator < Integer > ( ) {
public int compare ( Integer a, Integer b) {
return b- a;
}
} ) ;
for ( int i= 0 ; i< nums. length; i++ ) {
heap. offer ( nums[ i] ) ;
}
int ans= 0 ;
for ( int i= 0 ; i< k; i++ ) {
ans = heap. poll ( ) ;
}
return ans;
}
}
4. 46【全排列】- 回溯算法
题目: 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。代码:
class Solution {
List < List < Integer > > ans = new ArrayList < > ( ) ;
List < Integer > path = new LinkedList < > ( ) ;
public List < List < Integer > > permute ( int [ ] nums) {
boolean [ ] isUsed = new boolean [ nums. length] ;
Arrays . fill ( isUsed, false ) ;
backtrack ( nums, isUsed) ;
return ans;
}
public void backtrack ( int [ ] nums, boolean [ ] isUsed) {
if ( path. size ( ) >= nums. length) {
ans. add ( new ArrayList < > ( path) ) ;
return ;
}
for ( int i= 0 ; i< nums. length; i++ ) {
if ( isUsed[ i] ) continue ;
path. add ( nums[ i] ) ;
isUsed[ i] = true ;
backtrack ( nums, isUsed) ;
path. removeLast ( ) ;
isUsed[ i] = false ;
}
}
}
5. 55【跳跃游戏】- 贪心算法
题目: 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。代码:
class Solution {
public boolean canJump ( int [ ] nums) {
if ( nums. length == 1 ) return true ;
int loc = nums[ 0 ] ;
for ( int i= 0 ; i<= loc; i++ ) {
if ( nums[ i] + i > loc) {
loc = nums[ i] + i;
}
if ( loc>= nums. length- 1 ) {
return true ;
}
}
return false ;
}
}
6. 5【最长回文子串】- 动态规划
题目: 给你一个字符串 s,找到 s 中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。代码:
class Solution {
public String longestPalindrome ( String s) {
if ( s. length ( ) == 1 ) return s;
int n = s. length ( ) ;
boolean [ ] [ ] dp = new boolean [ n] [ n] ;
int index = 0 ;
int len = 0 ;
for ( int i= n- 1 ; i>= 0 ; i-- ) {
for ( int j= 0 ; j< n; j++ ) {
if ( s. charAt ( i) == s. charAt ( j) ) {
if ( j- i<= 1 ) {
dp[ i] [ j] = true ;
} else if ( dp[ i+ 1 ] [ j- 1 ] ) {
dp[ i] [ j] = true ;
}
if ( dp[ i] [ j] && len < j- i+ 1 ) {
index = i;
len = j- i+ 1 ;
}
} else {
dp[ i] [ j] = false ;
}
}
}
return s. substring ( index, index+ len) ;
}
}
7. 22【括号生成】- 回溯算法
题目: 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。代码:
class Solution {
List < String > ans = new ArrayList < > ( ) ;
StringBuilder sb = new StringBuilder ( ) ;
public List < String > generateParenthesis ( int n) {
backtrack ( 0 , 0 , n) ;
return ans;
}
public void backtrack ( int left, int right, int n) {
if ( sb. length ( ) == 2 * n) {
ans. add ( sb. toString ( ) ) ;
return ;
}
if ( left < n) {
sb. append ( '(' ) ;
backtrack ( left+ 1 , right, n) ;
sb. deleteCharAt ( sb. length ( ) - 1 ) ;
}
if ( right< left) {
sb. append ( ')' ) ;
backtrack ( left, right+ 1 , n) ;
sb. deleteCharAt ( sb. length ( ) - 1 ) ;
}
}
}
8. 39【组合总和】- 回溯算法
题目: 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 对于给定的输入,保证和为 target 的不同组合数少于 150 个。代码:
class Solution {
List < List < Integer > > ans = new ArrayList < > ( ) ;
List < Integer > path = new LinkedList < > ( ) ;
public List < List < Integer > > combinationSum ( int [ ] candidates, int target) {
backtrack ( candidates, target, 0 , 0 ) ;
return ans;
}
public void backtrack ( int [ ] candidates, int target, int index, int sum) {
if ( index>= candidates. length|| sum> target)
return ;
if ( sum == target) {
ans. add ( new ArrayList ( path) ) ;
return ;
}
for ( int i= index; i< candidates. length; i++ ) {
path. add ( candidates[ i] ) ;
sum += candidates[ i] ;
backtrack ( candidates, target, i, sum) ;
path. removeLast ( ) ;
sum -= candidates[ i] ;
}
}
}
9. 48【旋转图像】- 数组/双指针
题目: 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。代码:
class Solution {
public void rotate ( int [ ] [ ] matrix) {
int n = matrix. length;
int left = 0 ;
int right = n- 1 ;
int tmp;
while ( left< right) {
for ( int j= 0 ; j< n; j++ ) {
tmp = matrix[ left] [ j] ;
matrix[ left] [ j] = matrix[ right] [ j] ;
matrix[ right] [ j] = tmp;
}
left++ ;
right-- ;
}
for ( int i= 0 ; i< n; i++ ) {
for ( int j= 0 ; j< i; j++ ) {
tmp = matrix[ i] [ j] ;
matrix[ i] [ j] = matrix[ j] [ i] ;
matrix[ j] [ i] = tmp;
}
}
}
}
10. 53【最大子数组和】- 动态规划
题目: 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组是数组中的一个连续部分。代码:
class Solution {
public int maxSubArray ( int [ ] nums) {
int n = nums. length;
int [ ] dp = new int [ n] ;
dp[ 0 ] = nums[ 0 ] ;
int max = nums[ 0 ] ;
for ( int i= 1 ; i< n; i++ ) {
dp[ i] = Math . max ( dp[ i- 1 ] + nums[ i] , nums[ i] ) ;
max = Math . max ( dp[ i] , max) ;
}
return max;
}
}