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; }
}