7月1日的五题

718. 最长重复子数组

53. 最大子序和

54. 螺旋矩阵

55. 跳跃游戏

56. 合并区间

---------------------------------分割线-----------------------------------------

718. 最长重复子数组

Difficulty: 中等

给两个整数数组 AB ,返回两个数组中公共的、长度最长的子数组的长度。

示例 1:

输入:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
输出: 3
解释: 
长度最长的公共子数组是 [3, 2, 1]。

说明:

  1. 1 <= len(A), len(B) <= 1000
  2. 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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值