1.一维数组
1.1 寻找数组的中心索引
思路:
初步:拿到题的第一想法是嵌套循环,一个大循环里,两个小循环求和。但是在设置判断条件的时候为了判断左右两边和相等,且排除两边和为初始值0;一般情况下是可以的,但是两边(正负相加)和如果为0的话,就无法判断了。
代码如下(错误示范):
public static int centerindex(int a[]) {
int count=0;
for (int i=0;i<a.length;i++) {
int lsum,rsum;
lsum=0;
rsum=0;
for(int j=0;j<i;j++) {
lsum=lsum+a[j];
//System.out.println(j);
}
for (int k = i+1; k < a.length; k++) {
rsum=rsum+a[k];
//System.out.println(k);
}
if(lsum!=0&&rsum!=0&&lsum==rsum) {
count=i;
break;
}
}
if(count ==0)
return -1;
else
return count;
}
后来改进,先求整体和,然后从头开始减,判断减掉的部分与剩余的是否相等,注意记得减中间点x。
代码如下:
public static int centerindex2(int nums[]) {
int sum=0;
int []a=nums;
for(int i=0;i<a.length;i++)
sum=sum+a[i];
int temp=0;
for(int j=0;j<a.length;j++) {
if(temp==sum-temp-a[j]) {
return j;
}
temp+=a[j];
}
return -1;
}
1.2 至少是其他数字两倍的最大数
思路:
两步走,先找出数组中的最大值,并标记位置,第二步判断是否最大值是否是数组内其他值至少两倍大
对于判断两倍大,刚开始的思路进入误区,用最大值去除数组的每个数来判断,然后发现代码报错。应该是做完除法之后数据类型变了(盲猜的,不对请指正,欢迎指正!)
后来改用乘法来判断,通过了…
代码展示:
public static int panduan(int nums[]) {
int []a=nums;
int maxnum=a[0];
int temp=0;
int count=0;
for(int i=0;i<a.length;i++) {
if(a[i]>maxnum) {
maxnum=a[i];
temp=i;
}
}
for(int j=0;j<a.length;j++) {
if(a[j]*2<=maxnum)
count++;
}
if(count==a.length-1)
return temp;
else {
return -1;
}
}
1.3 加一
思路:
从数组的最后一位开始计算并判断,刚开始想用递归来做。发现太麻烦并且判断条件多。难解决的问题是9,99,999…这种情况,数组需要扩展。后来看了大佬的思路,顿时开阔了。重新初始化并扩长数组,然后首位置1,完美解决。其他情况的进位问题,先低位加1,然后用取余再判断来解决。
代码展示:
public static int[] add(int[] nums) {
for(int i=nums.length-1;i>=0;i--) {
nums[i]++;
nums[i]=nums[i]%10;
if(nums[i]!=0)
return nums;
}
nums=new int[nums.length+1];
nums[0]=1;
return nums;
}
1.4 合并区间
思路:
输入是一个二维数组,按区间的左端点对区间进行升序排列。将区间分为结果集和待比较集。
比较区间:将结果集的最后一个区间和遍历的待比较集的区间进行对比(实质是看是否有交集)
- 如果结果集最后一个区间的右端点小于待比较集的区间的左端点,说明这两个区间不相交,把这个待比较集的区间加到结果集;
- 否则,说明这两个区间相交,将这两个区间的右端点最大的那个设置为结果集最后一个区间的右端点。
PS:对数组排序涉及到一个函数Arrays.sort(intervals, Comparator.comparingInt(o -> o[0])); 是 Java8 以后提供的一种函数式编程语法
package com.shuzu;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class hebing {
public static int[][] merge(int[][] intervals){
int len=intervals.length;
if(len<2)
return intervals;
Arrays.sort(intervals,Comparator.comparingInt(o->o[0]));
List<int[]> result=new ArrayList<>();
result.add(intervals[0]);
for(int i=1;i<len;i++) {
int [] temp=intervals[i];
int [] rtemp= result.get(result.size()-1);
if (temp[0]>rtemp[1]) {
result.add(temp);
}
else {
rtemp[1]=Math.max(temp[1],rtemp[1]);
}
}
return result.toArray(new int[result.size()][]);
}
public static void main(String[] args) {
int[][] intervals = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};
int[][]res = merge(intervals);
for(int i=0;i<intervals.length;i++) {
System.out.println(Arrays.toString(res[i]));
}
}
}
2.二维数组
2.1 旋转矩阵
思路:
矩阵原地顺时针旋转90——>相当于
- 矩阵元素先以对角线为对称轴,交换元素。
- 然后,矩阵每行以中点为基准,交换元素。
代码:
class Solution {
public void rotate(int[][] matrix) {
int n=matrix.length;
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
int temp=matrix[i][j];
matrix[i][j]=matrix[j][i];
matrix[j][i]=temp;
}
}
int mid=n>>1;
for(int m=0;m<n;m++) {
for(int k=0;k<mid;k++) {
int temp2=matrix[m][k];
matrix[m][k]=matrix[m][n-1-k];
matrix[m][n-1-k]=temp2;
}
}
}
}
2.2零矩阵
思路:
用原数组的第一行跟第一例来标记需要清零的行和列,并且也要考虑本身第一行跟第一列也可能存在零的情况,所以设置hen,shu标签来判断。
并且在清零的时候,从每行或每列的第二位开始,因为在最开始遍历的时候第一位已经用来标记,设置为0了,不需要再清零,并且,也避免了第一位也清零的话,会覆盖掉标记位。
最后检查hen,shu,看看第一行或第一列是否也存在有0的情况,若是有,对第一行或第一列再清零。
代码
class Solution {
public void setZeroes(int[][] matrix) {
boolean hen=false;
boolean shu=false;
for(int i=0;i<matrix.length;i++) {
for(int j=0;j<matrix[0].length;j++) {
if(matrix[i][j]==0) {
if(i==0)
hen=true;
if (j==0) {
shu=true;
}
matrix[i][0]=0;
matrix[0][j]=0;
}
}
}
for(int i=1;i<matrix.length;i++) {
if(matrix[i][0]==0) {
for(int j=0;j<matrix[i].length;j++) {
matrix[i][j]=0;
}
}
}
for (int i = 1; i < matrix[0].length; i++) {
if(matrix[0][i]==0) {
for (int j = 0; j < matrix.length; j++) {
matrix[j][i]=0;
}
}
}
if(hen) {
for(int i=0;i<matrix[0].length;i++)
matrix[0][i]=0;
}
if (shu) {
for (int i = 0; i < matrix.length; i++) {
matrix[i][0]=0;
}
}
}
}
2.3 对角线遍历
思路:化繁为简,先不考虑先上后下的遍历顺序,只考虑按对角线遍历:
第一行跟最后一列的元素都是遍历的起点。外循环控制遍历次数,内循环控制每条对角线的遍历。在考虑对角线上遍历的时候,控制好边界。
第一次代码:在点的边界的定义上,数组越界了。好久才发现。当d=N时,起点的横纵坐标的值需要考虑清楚。
正确的:
代码
class Solution {
public int[] findDiagonalOrder(int[][] matrix) {
if (matrix==null||matrix.length==0) {
return new int[0];
}
int M=matrix.length;
int N=matrix[0].length;
int[] result= new int[N*M];
int count=0;
ArrayList<Integer> temp = new ArrayList<Integer>();
for(int d=0;d<M+N-1;d++ ) {
temp.clear();
int i=d<N?0:d-N+1;
int j=d<N?d:N-1;
while(i<M&&j>-1) {
temp.add(matrix[i][j]);
i++;
j--;
}
if(d%2==0) {
Collections.reverse(temp);
}
for (int k= 0; k< temp.size(); k++) {
result[count]=temp.get(k);
count++;
}
}
return result;
}
}