718. 最長重複子數組
53. 最大子序和
54. 螺旋矩陣
55. 跳躍遊戲
56. 合併區間
---------------------------------分割線-----------------------------------------
718. 最長重複子數組
Difficulty: 中等
給兩個整數數組 A
和 B
,返回兩個數組中公共的、長度最長的子數組的長度。
示例 1:
輸入:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
輸出: 3
解釋:
長度最長的公共子數組是 [3, 2, 1]。
說明:
- 1 <= len(A), len(B) <= 1000
- 0 <= A[i], B[i] < 100
Solution:動態規劃
(關鍵地方)定義狀態:dp[i][j]是以A[i]和B[j] 結尾 的字母的最長子數組的長度,這樣才需要更新狀態
class Solution {
public int findLength(int[] A, int[] B) {
//定義狀態:dp[i][j]是以A[i]和B[j]結尾的字母的最長子數組的長度吧,這樣才需要更新狀態
int[][] dp = new int[A.length+1][B.length+1];
int res = 0;
//初始化:[0][0]、[0][i]、[i][0]都是0
for(int i=1; i<=A.length; i++){
for(int j=1; j<=B.length; j++){
if(A[i-1] == B[j-1]) dp[i][j] = dp[i-1][j-1]+1;
else dp[i][j] = 0;
res = Math.max(dp[i][j], res);
}
}
return res;
}
}
53. 最大子序和
Difficulty: 簡單
給定一個整數數組 nums
,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子數組 [4,-1,2,1] 的和最大,爲 6。
進階:
如果你已經實現複雜度爲 O(n) 的解法,嘗試使用更爲精妙的分治法求解。
Solution:num[i] 之前的還要不要
class Solution {
public int maxSubArray(int[] nums) {
int count = nums[0], sum = nums[0];
for(int i=1; i<nums.length; i++){
if(count > 0){ //之前的大於0,我就要着
count += nums[i];
}
else{ //否則就把之前的丟棄掉
count = nums[i];
}
sum = Math.max(sum, count); // 每次都找最大值
}
sum = Math.max(sum, count);
return sum;
}
}
54. 螺旋矩陣
Difficulty: 中等
給定一個包含 m x n 個元素的矩陣(m 行, n 列),請按照順時針螺旋順序,返回矩陣中的所有元素。
示例 1:
輸入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
輸出: [1,2,3,6,9,8,7,4,5]
示例 2:
輸入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
輸出: [1,2,3,4,8,12,11,10,9,5,6,7]
Solution:確定四個角,這樣方便遍歷,注意:下 可能和 上 重複, 左 可能和 右 重複
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
int top, bottom, left, right, m, n;
m = matrix.length;
if(m <= 0) return res;
n = matrix[0].length;
if(n <= 0) return res;
// 固定四個角
top = 0;
left = 0;
bottom = m-1;
right = n-1;
while(top <= bottom && left <= right){ //一層一層的遍歷
for(int i=left; i<=right; i++){ //上
res.add(matrix[top][i]);
}
for(int i=top+1; i<=bottom; i++){ //右
res.add(matrix[i][right]);
}
if(top != bottom){
for(int i=right-1; i>=left; i--){ //下,可能和上重複
res.add(matrix[bottom][i]);
}
}
if(left != right){
for(int i=bottom-1; i>top; i--){ //左,可能和右重複
res.add(matrix[i][left]);
}
}
top++;
bottom--;
left++;
right--;
}
return res;
}
}
55. 跳躍遊戲
Difficulty: 中等
給定一個非負整數數組,你最初位於數組的第一個位置。
數組中的每個元素代表你在該位置可以跳躍的最大長度。
判斷你是否能夠到達最後一個位置。
示例 1:
輸入: [2,3,1,1,4]
輸出: true
解釋: 我們可以先跳 1 步,從位置 0 到達 位置 1, 然後再從位置 1 跳 3 步到達最後一個位置。
示例 2:
輸入: [3,2,1,0,4]
輸出: false
解釋: 無論怎樣,你總會到達索引爲 3 的位置。但該位置的最大跳躍長度是 0 , 所以你永遠不可能到達最後一個位置。
Solution:貪心算法,從右到左尋找最大的跳數
class Solution {
public boolean canJump(int[] nums) {
//貪心算法,從右到左尋找最大的跳數
int len = nums.length, index; //index表示當前位置
if(len <= 0) return false;
index = len-1;
while(index > 0){
int flag = index;
for(int i=index-1; i>=0; i--){
if(index-i <= nums[i]){
index = i;
}
}
if(flag == index) return false; //說明index沒變過
}
return true;
}
}
56. 合併區間
Difficulty: 中等
給出一個區間的集合,請合併所有重疊的區間。
示例 1:
輸入: [[1,3],[2,6],[8,10],[15,18]]
輸出: [[1,6],[8,10],[15,18]]
解釋: 區間 [1,3] 和 [2,6] 重疊, 將它們合併爲 [1,6].
示例 2:
輸入: [[1,4],[4,5]]
輸出: [[1,5]]
解釋: 區間 [1,4] 和 [4,5] 可被視爲重疊區間。
Solution:先對區間的第一維進行排序,然後找每個小區間的最大值和最小值
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
class Solution {
public int[][] merge(int[][] intervals) {
List<int[]> res = new ArrayList<>();
int len = intervals.length;
if(len <= 0) return new int[0][2];
quickSort(intervals); //排序
//尋找小區間的最大值和最小值:
//最小值一定是第一個區間的左邊
//最大值需要尋找
//如果某個區間的左邊,大於之前的最大值,說明這個區間和之前就不可能合併
int low = intervals[0][0], high = intervals[0][1];
for(int i=1; i<len; i++){
if(high < intervals[i][0]){ //區間的左邊大於之前的最大值,不能合併
int[] temp = new int[2];
temp[0] = low;
temp[1] = high;
res.add(temp);
low = intervals[i][0];
high = intervals[i][1];
}
else{
high = Math.max(high, intervals[i][1]);
}
}
int[] temp = new int[2];
temp[0] = low;
temp[1] = high;
res.add(temp);
int[][] val = new int[res.size()][2];
for(int i=0; i<res.size(); i++){
val[i] = res.get(i);
}
return val;
}
//---------------------隨機快速排序--------------------------
public void quickSort(int[][] intervals){
sortHelp(intervals, 0, intervals.length-1);
}
Random random = new Random();
public void sortHelp(int[][] intervals, int low, int high){
if(low > high) return;
int flag = random.nextInt(high-low+1)+low; //生成(low, high)之間的隨機數
int partition = intervals[flag][0];
swap(intervals, low, flag);
int l = low, h = high;
while(l < h){
while(l<h && intervals[h][0]>=partition){
h--;
}
if(l<h){
swap(intervals, l, h);
}
while(l<h && intervals[l][0]<=partition){
l++;
}
if(l<h){
swap(intervals, l, h);
}
}
sortHelp(intervals, low, l-1);
sortHelp(intervals, l+1, high);
}
public void swap(int[][] intervals, int i, int j){
int[] temp = intervals[i];
intervals[i] = intervals[j];
intervals[j] = temp;
}
}