數組
尋找兩個正序數組的中位數
連結:
https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n1 = nums1.length;
int n2 = nums2.length;
int[] nums = new int[n1 + n2];
System.arraycopy(nums1, 0, nums, 0, n1);
System.arraycopy(nums2, 0, nums, n1, n2);
Arrays.sort(nums);
int n = nums.length;
if (n % 2 == 0) {
return (nums[(n/2)-1] + nums[n/2])/2.0;
} else {
return nums[n/2];
}
}
}
二分查找
https://leetcode-cn.com/problems/binary-search/
class Solution {
public int search(int[] nums, int target) {
int start = 0;
int end = nums.length-1;
int mid = -1;
while(start <= end){
mid = (end-start)/2+start;
if(nums[mid] == target){
return mid;
}
if(nums[mid] > target){
end = mid -1;
}
if(nums[mid]<target){
start=mid+1;
}
}
return -1;
}
}
其他
跳躍遊戲
這題應該可以采用動态規劃的思想,但參考了其他方法。
https://leetcode-cn.com/problems/jump-game/
class Solution {
public boolean canJump(int[] nums) {
if (nums == null){
return false;
}
int k = 0;
int n =nums.length;//數組的長度
for(int i = 0; i<n ;i++){
if(i>k){
return false;
}
k = Math.max(k,i+nums[i]);
}
return true;
}
}
動态規劃
裴波那契數列
https://leetcode-cn.com/problems/fibonacci-number/
class Solution {
public int fib(int n) {
int[] dp = new int[n + 100];
dp[0] = 0;
dp[1] = 1;
for(int i = 2;i<=n;i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
}
裴波那契數列的變形題有:
- 第 N 個泰波那契數(1137):
https://leetcode-cn.com/problems/n-th-tribonacci-number/
- 爬樓梯(70):
https://leetcode-cn.com/problems/climbing-stairs/
打家劫舍——線形
-
(1)解法https://leetcode-cn.com/problems/Gu0c2T/
class Solution {
public int rob(int[] nums) {
int n =nums.length;
if(n == 0) return 0;
if(n == 1) return nums[0];
int[] arr = new int[n+1];
arr[0] = nums[0];
arr[1] = Math.max(nums[0],nums[1]);
for(int i=2;i<n;i++){
arr[i] = Math.max(arr[i-1],arr[i-2]+nums[i]);
}
return arr[n-1];
}
}
類似題:
按摩師:
https://leetcode-cn.com/problems/the-masseuse-lcci/
打家劫舍——環形
https://leetcode-cn.com/problems/house-robber-ii/
解法思路:
環狀排列意味着第一個房子和最後一個房子中隻能選擇一個偷竊,是以可以把此環狀排列房間問題約化為兩個單排排列房間子問題:
- 在不偷竊第一個房子的情況下(即 nums[1:]nums[1:]nums[1:]),最大金額是 p1p_1p1
- 在不偷竊最後一個房子的情況下(即 nums[:n−1]nums[:n-1]nums[:n−1]),最大金額是 p2p_2p2
- 綜合偷竊最大金額: 為以上兩種情況的較大值,即 max(p1,p2)max(p1,p2)max(p1,p2)
另外,需要特别介紹Java中的Arrays.copyOfRange()方法,要引用 import java.util.Arrays;
- 這個方法主要是用來進行數組的複用,我遇到這個方法是在遞歸函數的調用中,這個方法比較的普遍,能夠優化代碼的結構。
-
此時要注意下标的變化,array=Arrays.copyOfRange(oringinal,int from, int to)
拷貝array
數組從from下标開始,一直到original
下标結束,注意包含to
下标,不包含from
下标,是左閉右開區間。to
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n == 0) return 0;
if(n == 1) return nums[0];
return Math.max(x_rob(Arrays.copyOfRange(nums, 0, n - 1)),
x_rob(Arrays.copyOfRange(nums, 1, nums.length)) );
}
public int x_rob(int[] nums) {
int n =nums.length;
if(n == 0) return 0;
if(n == 1) return nums[0];
int[] arr = new int[n+1];
arr[0] = nums[0];
arr[1] = Math.max(nums[0],nums[1]);
for(int i=2;i<n;i++){
arr[i] = Math.max(arr[i-1],arr[i-2]+nums[i]);
}
return arr[n-1];
}
}
零錢兌換
https://leetcode-cn.com/problems/coin-change/
思路:
首先:貪心算法未必能拿到最優解
解題的思路是動态規劃:
- (1)定義數組dp[],其中dp[i]表示金額的最優解,即為組成金額i最少使用的鈔票數量
- (2)計算金額amount的最優解,則需要dp數組的長度為amount+1,進而表示0到金額amount的最優解
- (3)最初dp數組所有元素初始化為-1,dp[0]為金額0的最優解初始化為0,完成dp數組的計算後,将金額amount的最優解dp[amount]傳回
class Solution {
public int coinChange(int[] coins, int amount) {
int n = coins.length;
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount+1);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < n; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
删除并獲得點數
連結(740):https://leetcode-cn.com/problems/delete-and-earn/
class Solution {
public int deleteAndEarn(int[] nums) {
int n = nums.length;
if(n == 0) return 0;
if(n == 1) return nums[0];
//找出數組裡的最大數
int max = nums[0];
for(int i = 1;i<n;i++){
max = Math.max(max,nums[i]);
}
//構造新的數組dp
int[] sum = new int[ max + 1 ];
for (int item : nums) {
sum[item] ++;
}
//動态規劃
int[] dp = new int[max + 1];
dp[1] = sum[1] * 1;
dp[2] = Math.max(dp[1], sum[2] * 2);
for (int i = 2; i <= max; ++i) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + i * sum[i]);
}
return dp[max];
}
}
最大子數組和
連結(53):
https://leetcode-cn.com/problems/maximum-subarray/
class Solution {
public int maxSubArray(int[] nums) {
// f(i)=max{f(i−1)+nums[i],nums[i]}
int n = nums.length;
//int[] dp = new int[n+1];
int pre = 0,maxAns = nums[0];
for(int i = 0;i<n;i++){
pre = Math.max(pre+nums[i],nums[i]);
maxAns = Math.max(maxAns,pre);
}
return maxAns;
}
}
買賣股票的最佳時機
連結(121):
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/
class Solution {
public int maxProfit(int[] prices) {
if(prices.length <= 1)
return 0;
int min = prices[0], max = 0;
for(int i = 1; i < prices.length; i++) {
//記錄最小買入值
min = Math.min(min, prices[i]);
//記錄利潤最大值
max = Math.max(max, prices[i] - min);
}
return max;
}
}
最佳觀光組合
連結(1014):
https://leetcode-cn.com/problems/best-sightseeing-pair/
class Solution {
public int maxScoreSightseeingPair(int[] values) {
int n = values.length,mx = values[0] + 0,ans = 0;
for(int j = 1; j < n; j++){
ans = Math.max(ans , mx + values[j] - j);
mx = Math.max(mx, values[j] + j);
}
return ans;
}
}