目录
普通数组&矩阵
最大子数组和
题目
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组是数组中的一个连续部分。
代码
cpp
class Solution {
public int maxSubArray(int[] nums) {
//贪心解法 如果连续和+nums[i]只会拖累nums[i]的话 就让起始从i开始
//连续和变成负数的时候再跳过
int res=-99999;
int count=0;//累加连续和
for(int i=0;i<nums.length;i++){
count+=nums[i];
if(count>res) res=count;
if(count<0) count=0;
}
return res;
// int len=nums.length;
// // dp[i] 表示 nums 中以 nums[i] 结尾的最大子序列和
// int[] dp = new int[len];
// dp[0] = nums[0];
// int maxRes = dp[0];
// for (int i = 1; i < len; i++) {
// dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
// maxRes = Math.max(maxRes, dp[i]);
// }
// return maxRes;
}
}
合并区间
题目
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
代码
cpp
class Solution {
public int[][] merge(int[][] intervals) {
//双向链表结构
LinkedList<int[]> res = new LinkedList<>();
// 按区间的 start 升序排列
Arrays.sort(intervals, (a, b) ->a[0]-b[0]);
res.add(intervals[0]);
for (int i = 1; i < intervals.length; i++) {
int[] curr = intervals[i];
// res 中最后⼀个元素的引⽤
int[] last = res.getLast();
if (curr[0] <= last[1]) {
last[1] = Math.max(last[1], curr[1]);
} else {
// 处理下⼀个待合并区间
res.add(curr);
}
}
return res.toArray(new int[0][0]);
}
}
轮转数组
题目
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
代码
cpp
class Solution {
public void rotate(int[] nums, int k) {
//给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数
List<Integer> ls=new ArrayList<>();
int len=nums.length;//7 k:3
k=k%len;
for(int i=len-k;i<len;i++){
ls.add(nums[i]);
}
for(int i=0;i<len-k;i++){
ls.add(nums[i]);
}
for(int i=0;i<len;i++){
nums[i]=ls.get(i);
}
}
}
除自身以外数组的乘积
题目
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。
代码
cpp
class Solution {
public int[] productExceptSelf(int[] nums) {
// answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积
// 题目数据保证数组 nums 之中任意元素的全部前缀元素和后缀的乘积都在 32 位整数范围内
// 请不要使用除法,且在 O(n) 时间复杂度内完成此题
// 考虑如何有效地利用前缀和后缀乘积来计算每个索引中除 self 之外的所有元素的乘积
// 能否在线性时间内预先计算前缀和后缀乘积以避免冗余计算
// 通过重用内存或修改输入数组来存储中间结果来最小化额外的空间使用
int n = nums.length;
int[] tempz = new int[n];
int[] tempy = new int[n];
int[] res = new int[n];
// 预处理 nums 中当前数字的前缀之积 从前向后遍历
tempz[0] = 1;
for (int i = 1; i < n; i++) {
tempz[i] = tempz[i - 1] * nums[i - 1];
}
// 预处理 nums 中当前数字的后缀之积 从后向前遍历
tempy[n - 1] = 1;
for (int j = n - 2; j >= 0; j--) {
tempy[j] = tempy[j + 1] * nums[j + 1];
}
// 计算最终结果
for (int i = 0; i < n; i++) {
res[i] = tempz[i] * tempy[i];
}
return res;
}
}
缺失的第一个正数
题目
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
代码
cpp
class Solution {
private void swap(int[] nums, int index1, int index2) {
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
}
public int firstMissingPositive(int[] nums) {
int len = nums.length;
//整理输入数组整理成我们想要的那个样子
for (int i = 0; i < len; i++) {
//交换后的数跟原先位置上的数一致的话就没有必要交换
while (nums[i] >= 1 && nums[i] <= len && nums[nums[i] - 1] != nums[i]) {
// 满足在指定范围内、并且没有放在正确的位置上,才交换
// 例如:数值 3 应该放在索引 2 的位置上
swap(nums, i, nums[i] - 1 );
}
}
// [1, -1, 3, 4]
for (int i = 0; i < len; i++) {
if (nums[i] != i + 1) {//当前的数等于下标+1
return i + 1;
}
}
// 都正确则返回数组长度 + 1
return len + 1;
}
}
矩阵置零
题目
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
代码
cpp
class Solution {
public void setZeroes(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
boolean row_flag = false;
boolean col_flag = false;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(matrix[i][j]==0){
//如果该位置上的数为0的话 将该数第一行 和第一列的数设置为0
matrix[0][j]=0;
matrix[i][0]=0;
//如果这个位置在第一行 第一列
if(i==0) row_flag=true;
if(j==0) col_flag=true;
}
}
}
//根据第一行第一列中0的位置 对剩余数字置0
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
if(matrix[i][0]==0||matrix[0][j]==0){
matrix[i][j]=0;
}
}
}
//根据行标记和列标记 将第一行和第一列置为0
for(int i=0;col_flag&&i<m;i++) matrix[i][0]=0;
for(int j=0;row_flag&&j<n;j++) matrix[0][j]=0;
}
}
螺旋矩阵
题目
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
代码
cpp
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
//返回矩阵中的所有元素
int l=0;
int r=matrix[0].length-1;//2
int t=0;
int b=matrix.length-1;
if(matrix.length==0) return new ArrayList<>();
List<Integer> ls=new ArrayList<>();
while(true){
//从左到右
for(int i=l;i<=r;i++){
ls.add(matrix[l][i]);
}
t++;
if(t>b) break;//上边界下移动 越界的话 直接跳出循环
//从上到下
for(int i=t;i<=b;i++){//t:1 b:2 i:1 2
ls.add(matrix[i][r]);
}
r--;
if(r<l) break;//右边界左移
//从右到左
for(int i=r;i>=l;i--){//i:1 0
ls.add(matrix[b][i]);
}
b--;
if(b<t) break;//下边界上移
//从下到上
for(int i=b;i>=t;i--){//i:1
ls.add(matrix[i][l]);
}
l++;
if(l>r) break;//左边界右移
}
return ls;
}
}
旋转图像
题目
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
代码
cpp
class Solution {
public void rotate(int[][] matrix) {
int n=matrix.length;
//主对角线进行翻转
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
int temp=matrix[i][j];
matrix[i][j]=matrix[j][i];
matrix[j][i]=temp;
}
}
//左右翻转
for(int i=0;i<n;i++){
for(int j=0;j<n/2;j++){//n:4
int temp=matrix[i][j];
matrix[i][j]=matrix[i][n-j-1];
matrix[i][n-j-1]=temp;
}
}
}
}
搜索二维矩阵 II
题目
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
代码
cpp
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//将二维数组的元素全部放进一维数组中 然后进行二分查找
List<Integer> ls=new ArrayList<Integer>();
int m=matrix.length;
int n=matrix[0].length;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
ls.add(matrix[i][j]);
}
}
Collections.sort(ls);
int l=0,r=ls.size()-1;
while(l<r){
int mid=l+r>>1;
if(ls.get(mid)>=target){
r=mid;
}else{
l=mid+1;
}
}
if(ls.get(l)==target){
return true;
}else{
return false;
}
}
}