最大子数组和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [5,4,-1,7,8]
输出:23
需要一个变量pre保存连续子数组的和,每次加后面的值的时候都要与此时需要加的值做对比,如果比小他说明之前的的子数组的值并不为最大。如果比他大,继续。
此时pre保存的是遍历到此处的子数组的和,可能是最大可能不是。所以需要一个变量maxAns来保存每次遍历获取到的最大的子数组的和。这个值每次遍历都会与pre中的值作对比,如果比他大就不需要更新,如果比他小就需要更新,来保存新获取的最大子串和。
class Solution {
public int maxSubArray(int[] nums) {
int pre=0,maxAns=nums[0];
for(int i : nums){
pre=Math.max(pre+i,i);
maxAns=Math.max(maxAns,pre);
}
return maxAns;
}
}
整体流程:
整个所有的子数组的值保存在a[n]中。pre=a[i],显然若pre的值比下一个要累加的值小的话该数组就不是最大子串和。maxAns为a[i]和a[i-1]中的较大值。遍历完成后获得maxAns为最大子串和。
知识点:
for(int i : nums)
等同于for 循环。此时的i不是标号而是代表nums数组里的值。
Math.max()获取参数中的最大值。
存在重复元素
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。
示例 1:
输入:nums = [1,2,3,1]
输出:true
示例 2:
输入:nums = [1,2,3,4]
输出:false
示例 3:
输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true
该题目需要找到是否有2个以上的相同的值。
采取排序更快。
法一:
class Solution {
public boolean containsDuplicate(int[] nums) {
Arrays.sort(nums);
for(int i=0;i<nums.length-1;i++){
if(nums[i]==nums[i+1])
return true;
}
return false;
}
}
知识点
Arrays.sort()对数组进行排序,默认为升序。
法二:
class Solution {
public boolean containsDuplicate(int[] nums) {
return Arrays.stream(nums).distinct().count<nums.length;
}
}
很简单,调用stream().distinct()方法输出由该流的不同元素组成的流。count来统计不同元素的个数,显然由于返回值为boolean类型,若没有重复值返回false,若有相同元素肯定是小于数组长度。
知识点:
stream().distinct()
distinct()返回由该流的不同元素组成的流。
两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
采取循环遍历法,由于同一元素不能重复出现,所以直到目标值可得到即可输出。
class Solution{
public int[] twoSum(int []nums,int target){
for(int i=0;i<nums.length-1;i++){
for(int j=i+1;j<nums.length;j++){
if((nums[i]+nums[j])==target)
return new int[]{i,j};
}
}
return new int[0];
}
}
知识点:
return new int[]{i,j};
这里是一个数组的静态赋值。
return new int[0];
这里返回一个空数组。
合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
不难想到先把nums2数组元素放入nums1数组中再进行排序。
class Solution{
public void merage(int nums1[],int m,int []nums2,int n){
for(int i=0;i<n;i++)
nums1[m+i]=nums2[i];
Arrays.sort(nums1);
}
}
两个数组的交集
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
考虑将两个数组进行排序,之后进行对比如果相同放在新数组中。
class Solution{
public int[] intersect(int[] nums1,int[] nums2){
Arrays.sort(nums1);
Arrays.sort(nums2);
int index=0,index1=0,index2=0;
int length1=nums1.length;
int length2=nums2.length;
int[] intersection= new int[Math.min(length1,length2)];
while(index1<length1&&index2<length2){
if(nums1[index1]<nums2[index2])
index1++;
else if(nums1[index1]>nums2[index2])
index2++;
else{
intersection[index]=nums1[index1];
index++;
index1++;
index2++;
}
}
return Arrays.copyOfRange(intersection,0,index);
}
}
知识点:Arrays.copyOfRange
Arrays.copyOfRange(T[ ] original,int from,int to)
将一个原始的数组original,从下标from开始复制,复制到上标to,生成一个新的数组。
注意这里包括下标from,不包括上标to。
买卖股票的最佳时机
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
法一:
可以考虑设置一个pre变量保存当前遍历的最大利润,一个max变量保存最大利润,每次遍历结束都要与最大利润进行对比,最大利润小于0,则最大利润返回0;
class Solution{
public int maxProfit(int[] prices){
int pre=0;
int max=0;
for(int i=0;i<prices.length-1;i++){
for(int j=i+1;j<prices.length;j++){
pre=prices[j]-prices[i];
if(pre>max)
max=pre;
}
}
return max;
}
}
法二:
记录最小的值,在每次遍历时保存遍历值与此最小值的差,直到遍历结束,输出最大。
class Solution{
public int maxProfit(int[] prices){
int min=Integer.MAX_VALUE;
int max=0;
for(int i=0;i<prices.length;i++){
if(min>prices[i])
min=prices[i];
else if(prices[i]-min>max){
max=prices[i]-min;
}
}
return max;
}
}
知识点:
Integer.MAX_VALUE表示int数据类型的最大取值数:2 147 483 647
Integer.MIN_VALUE表示int数据类型的最小取值数:-2 147 483 648
该值通常在初始化时使用,用于表示无穷大或无穷小
重塑矩阵
在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。
给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。
如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。
示例 1:
输入:mat = [[1,2],[3,4]], r = 1, c = 4
输出:[[1,2,3,4]]
示例 2:
输入:mat = [[1,2],[3,4]], r = 2, c = 4
输出:[[1,2],[3,4]]
这道题需要考虑如何能把矩阵中的值一一对应赋值到新创建的矩阵中。
由于标号从0开始,所以可以想到这个m*n的矩阵的中的第(i,j)个元素的标号x为i×n+j。
我们得到:
行号i=x/n
列号j=x%n
class solution{
public int[][] matrixReshape(int[][] mat,int r,int c){
int m=mat.length;
int n=mat[0].length;
if(m*n!=r*c){
return mat;
}
int[][] ans=new int[r][c];
for(int x=0;x<m*n;x++){
ans[x/c][x%c]=mat[x/n][x%n];
}
return ans;
}
}
杨辉三角
给定一个非负整数 *numRows
,*生成「杨辉三角」的前 numRows
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
示例 1:
输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
示例 2:
输入: numRows = 1
输出: [[1]]
显然这个三角是作为一个二维矩阵,以对角线为界,取下面部分数据输出得到。
所以我们需要输出的范围用代码表示为:
for(int i=0 ; i<numRows;i++){
for(int j=0;j<=i;j++)
}
这里注意,对角线上数据也要输出。
根据题目观察到若一行有n个数据,第一个和第n个数据都为1。所以得到:
if(j0||ji),直接填充1。
中间元素的值等于它的左上角和右上角数值的和。
在数组里表示为。中间元素下标为(i,j),左上角为(i-1,j-1),右上角为(i-1,j);
代码:
class Solution{
public List<List<Integer>> generate(int numRows){
List<List<Integer>> ret = new ArrayList<List<Integer>>();
for(int i=0;i<numRows;i++){
List<Integer> row = new ArrayList<Integer>();
for(int j=0;j<=i;j++){
if(j==0||j==i){
row.add(1);
}else{
row.add(ret.get(i-1).get(j-1)+ret.get(i-1).(j));
}
}
ret.add(row);
}
return ret;
}
}
有效的数独
请你判断一个 9 x 9
的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。(请参考示例图)
注意:
- 一个有效的数独(部分已被填充)不一定是可解的。
- 只需要根据以上规则,验证已经填入的数字是否有效即可。
- 空白格用
'.'
表示。
示例 1:
输入:board =
[["5","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
输出:true
示例 2:
输入:board =
[["8","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
输出:false
解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
我们采取建立二维数组rows和columns分别表示行和列。
其中row[i][n-1]
代表i行中数字n出现的次数。columns[j][n-1]
代表j列中数字n出现的次数。数字n从1~9。
创建一个三维数组subboxes这个数组表示每个3X3的的矩阵中对应数字出现的次数。一行中最多有3个此类矩阵。所以我们采用【i/3】【j/3】来得到对应矩阵的标号。即subboxes[i/3][i/3][n-1]
存储对应n-1出现的次数。
我们在判断出对应borad[i][j]
填写的数字后需要将所有对应的数字计数进行+1。最后如果得到三个数组中有数字大于1那么就说明此矩阵并不符合9宫格。
class Solution{
public boolean isValidSudoku(int[][] board){
int[][] rows=new int[9][9];
int[][] cloumns=new int[9][9];
int[][][] subboxes=new int[3][3][9];
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
char c=board[i][j];
if(c!='.'){
int index=c-'0'-1;
rows[i][index]++;
cloumns[j][index]++;
subboxes[i/3][j/3][index]++;
if(rows[i][index]>1|| cloumns[j][index]>1||subboxes[i/3][j/3][index]>1){
return false;
}
}
}
}
return true;
}
}
矩阵置零
给定一个 *m* x *n*
的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法**。**
示例 1:
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]
示例 2:
输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
创建两个标记数组,rows,columns分贝表示行和列,如果对应的i行j列元素为0则,rows[i]=columns[j]=true;
之后再遍历数组更新就可以。
class Solution{
public void setZeroes(int[][] matrix){
int m=matrix.length;
int n=matrix[0].length;
boolean[] rows=new boolean[m];
boolean[] columns=new boolean[n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(matrix[i][j]==0){
rows[i]=columns[j]=true;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(rows[i]||columns[j]){
matrix[i][j]=0;
}
}
}
}
}