leetcode-day5

48.给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

class Solution {
    public void rotate(int[][] matrix) {//原地旋转,找规律
        int n = matrix.length;
        for (int i = 0; i < n / 2; ++i) {
            for (int j = 0; j < (n + 1) / 2; ++j) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n - j - 1][i];
                matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
                matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                matrix[j][n - i - 1] = temp;
            }
        }
    }
}

53.给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
贪心:

class Solution {
     public int maxSubArray(int[] nums) {
    /*
     * 	题目要求我们只求最优解,即获取最大的值,那么很容易会考虑到贪心算法
     * 	我们需要考虑到贪心抛弃,当你的tmp值加到负值的时候,那么前面的子串和后面的字符组合只会造成负面影响(贪心负影响,通俗的说就是前面子串和后面组合还不如后面本身大),因此,我们贪心地舍弃掉前面的子串,重新建立子串找最大值
     * 	
     */
    	int ans = nums[0];
    	//保存临时值
    	int tmp = 0;
    	for(int num : nums) {
            tmp += num;
            if(tmp > ans) 
                ans = tmp;
    		if(tmp < 0) 
                tmp = 0;
    	}
    	return ans;
    }
};

动态规划:
在这里插入图片描述

class Solution {
    public int maxSubArray(int[] nums) {
        int pre = 0, ans = nums[0];
        for (int num : nums) {
            pre = Math.max(pre + num, num); //决定加还是不加
            ans = Math.max(ans, pre); //更新最大值
        }
        return ans;
    }
}

55.给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
贪心:

public class Solution {
    public boolean canJump(int[] nums) {
        int n = nums.length, rightmost = 0;
        for (int i = 0; i < n; i++) {
            if (i <= rightmost) {
                //及时更新能到达的最远的距离
                rightmost = Math.max(rightmost, i + nums[i]); 
                //当能到达的最远距离超过或等于最后一个,返回true
                if (rightmost >= n - 1) {
                    return true;
                }
            }
        }
        return false;
    }
}

动态规划:

public class Solution {
    public boolean canJump(int[] nums) {
        int n = nums.length;
        boolean[] dp = new boolean[n];
        dp[0] = true; //初始化,因为最初位于数组的第一个下标
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (dp[j] && j + nums[j] >= i) {
                    dp[i] = true; //dp[i]=true说明i位置能跳到
                    break;
                }
            }
        }
        return dp[n - 1];
    }
}

56.以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

class Solution {
    public int[][] merge(int[][] intervals) {
        //length=0在本题中不用考虑,因为提示中已知1<=intervals.length<=104
        // if (intervals.length == 0) { 
        //     return new int[0][2];
        // }
        Arrays.sort(intervals, new Comparator<int[]>() {//哇,还可以这样排序,孤陋寡闻了
            public int compare(int[] interval1, int[] interval2) {
                return interval1[0] - interval2[0];
            }
        });
        List<int[]> merged = new ArrayList<int[]>();
        for (int i = 0; i < intervals.length; ++i) {
            int L = intervals[i][0], R = intervals[i][1];
            //如果当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合,
            //我们可以直接将这个区间加入数组 merged 的末尾。
            if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) {
                merged.add(new int[]{L, R});
            } else {
            //否则,它们重合,
            //我们需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,将其置为二者的较大值。(因为按左端点排得序,所以不用考虑左端点了。)
                merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R); 
            }
        }
        return merged.toArray(new int[merged.size()][]);
    }
}

62.一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
动态规划:

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] f = new int[m][n];
        //边界条件初始化
        for (int i = 0; i < m; ++i) {
            f[i][0] = 1;
        }
        for (int j = 0; j < n; ++j) {
            f[0][j] = 1;
        }
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                //每个点的到达方式之和由左和上两个点决定(路径的叠加)
                f[i][j] = f[i - 1][j] + f[i][j - 1]; 
            }
        }
        return f[m - 1][n - 1];
    }
}

动态规划优化:

class Solution {
    public int uniquePaths(int m, int n) {
        int[] cur = new int[n];
        Arrays.fill(cur,1); //边界条件初始化
        for (int i = 1; i < m; i++){
            for (int j = 1; j < n; j++){
                cur[j] += cur[j-1] ;
            }
        }
        return cur[n-1];
    }
}

组合数学:
在这里插入图片描述

class Solution {
    public int uniquePaths(int m, int n) {
        long ans = 1;
        for (int x = n, y = 1; y <= m-1; ++x, ++y) {
            ans = ans * x / y; //x为n到m+n-2;y为1到m-1(调整了y运算顺序)
        }
        return (int) ans;
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值