01 如何寻找数组中的最小值与最大值
static int Max;
static int Min;
public static void getMaxAndMin(int arr[]){
Max =arr[0];
Min =arr[0];
int len =arr.length;
for (int i=0;i<len-1;i=i+2){
if (i+1>len){
if (arr[i]>Max)
Max =arr[i];
if (arr[i]<Min)
Min =arr[i];
}
if (arr[i]>arr[i+1]){
if (arr[i]>Max)
Max=arr[i];
else if (arr[i+1]<Min)
Min=arr[i+1];
}
if (arr[i]<arr[i+1]){
if (arr[i+1]>Max)
Max=arr[i+1];
else if (arr[i]<Min)
Min=arr[i];
}
}
}
public static void main(String[] args) {
int[] array={7,9,1,5,0,6,4,3};
getMaxAndMin(array);
System.out.println("Max = "+Max);
System.out.println("Min = "+Min);
}
02 如何找出数组中的第二大的数
先定义两个变量,一个变量用来存储数组的最大值,另一个存储数组第二大的值。遍历数组如果数组元素比最大值大。第二大的值更新为之前最大值,最大值也更新。如果比最大值小,比较第二大的值。如果比第二大的值大。更新第二大的值。
public static int findSecMax(int arr[]){
int max=arr[0];
int secMax=Integer.MIN_VALUE;
for (int i=1;i<arr.length;i++){
if (arr[i]>max){
secMax=max;
max=arr[i];
}else{
if (arr[i]>secMax){
secMax=arr[i];
}
}
}
return secMax;
}
public static void main(String[] args) {
int[] array={7,9,1,5,0,6,4,3};
System.out.println(findSecMax(array));
}
03 如果求最大子数组之和
方法一:蛮力法
找出所有子数组,然后求出子数组的和。在所有子数组的和中取最大值。
public static int getMaxSubArray(int arr[]){
int MaxSub=0;
for (int i=0;i<arr.length;i++){
for (int j=i;j<arr.length;j++){
int ThisSub=0;
for (int k=i;k<j;k++){
ThisSub+=arr[k];
}
if (ThisSub>MaxSub){
MaxSub=ThisSub;
}
}
}
return MaxSub;
}
public static void main(String[] args) {
int[] array={7,-9,1,-10,0,-12,4,10,3,12};
System.out.println(getMaxSubArray(array));
}
方法二:重复利用已经计算的子数组和
例如:sum[ i , j ] = sum[ i , j - 1 ] + arr[ j ] ,采用这种方法可以省去计算sum[i , j - 1 ]的时间。
public static int getMaxSubArray1(int arr[]){
int maxSub=0;
for(int i=0;i<arr.length;i++){
int sum=0;
for (int j=i;j<arr.length;j++){
sum+=arr[j];
if (maxSub<sum)
maxSub=sum;
}
}
return maxSub;
}
public static void main(String[] args) {
int[] array={7,-9,1,-10,0,-12,4,10,3,12};
System.out.println(getMaxSubArray1(array));
}
方法三:动态规划方法
public static int max(int m,int n){
return m>n?m:n;
}
public static int getMaxSubArray2(int arr[]){
int n=arr.length;
int End[]=new int[n];
int All[]=new int[n];
End[n-1]=arr[n-1];
All[n-1]=All[n-1];
End[0]=All[0]=arr[0];
for (int i=1;i<n;i++){
End[i]=max(End[i-1]+arr[i],arr[i]);
All[i]=max(End[i],All[i-1]);
}
return All[n-1];
}
public static void main(String[] args) {
int[] array={7,-9,1,-10,0,-12,4,10,3,12};
System.out.println(getMaxSubArray2(array));
}
方法四:优化动态规划
方法三中每次只用End[ i-1 ] 与 All[ i- 1 ] ,而不是整个数组中的值,因此可以定义两个变量来保存End[ i - 1 ] 的值,并且反复利用。
public static int max(int m,int n){
return m>n?m:n;
}
public static int getMaxSubArray3(int arr[]){
int n=arr.length;
int nAll=arr[0];//有n个数字数组的最大子数组和
int nEnd=arr[0];//有n个数字数组包含最后一个元素的子数组的最大和
for (int i=1;i<n;i++){
nEnd=max(nEnd+arr[i],arr[i]);
nAll=max(nEnd,nAll);
}
return nAll;
}
public static void main(String[] args) {
int[] array={7,-9,1,-10,0,-12,4,10,3,12};
System.out.println(getMaxSubArray3(array));
}
引申:在指导子数组中的最大和之后,如何才能确定最大子数组的位置呢?
private static int begin=0;//记录最大子数组的起始位置
private static int end=0;//记录最大子数组的结束位置
public static int getMaxSubArray(int []arr){
int maxSum=Integer.MIN_VALUE;//子数组最大值;
int nSum=0;//包含最后一位的最大值
int nStart=0;
for (int i=0;i<arr.length;i++){
if (nSum<0){
nSum=arr[i];
nStart=i;
}else {
nSum+=arr[i];
}
if (nSum>maxSum){
maxSum=nSum;
begin=nStart;
end=i;
}
}
return maxSum;
}
public static void main(String[] args) {
int[] array={7,-9,1,-100,0,-12,4,-100,3,12};
System.out.println(getMaxSubArray(array));
System.out.println("begin:"+array[begin]+" end:"+array[end]);
}
04 如何找出数组中重复元素最多的数
使用Map映射表,来纪律每一个元素出现的次数,然后判断次数大小。
private static int result;
private static int val;
public static void findMostFrequentInArray(int arr[]){
Map<Integer,Integer> m=new HashMap<>();
for (int i=0;i<arr.length;i++){
if (m.containsKey(arr[i])){
m.put(arr[i],m.get(arr[i])+1);
}else {
m.put(arr[i],1);
}
}
//找出出现次数最多的元素
Iterator<Map.Entry<Integer, Integer>> iter = m.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<Integer, Integer> entry = iter.next();
int key = entry.getKey();
int value = entry.getValue();
if (result<value){
result=value;
val=key;
}
}
}
public static void main(String[] args) {
int[] array={1,2,1,2,4,5,1,2,1,2,3,2,2,4,1,5};
findMostFrequentInArray(array);
System.out.println("数:"+val);
System.out.println("个数:"+result);
}
05 如何求数组中俩俩相加等于10的组合种数
方法一:蛮力法
采用双重循环遍历数组来判断两个数的和是否为20
public static void findSum(int arr[],int sum){
int len = arr.length;
for (int i=0;i<len;i++){
for (int j=i+1;j<len;j++){
if (arr[i]+arr[j]==sum)
System.out.println("两个数为:"+arr[i]+" "+arr[j]);
}
}
}
public static void main(String[] args) {
int array[]={1,9,5,4,6,3,7,2,8,11,10};
findSum(array,10);
}
方法二:排序法
先对数组进行排序(快速排序或堆排序),然后对排序后的数组从前到后和从后到前遍历,满足arr[begin]+arr[end]<10 ,那就组合就在 arr[begin+1]+arr[end] 寻找,如果arr[begin]+arr[end]>10 ,就在 arr[begin]+arr[end - 1 ]寻找
public static void findSum1(int arr[],int sum){
Arrays.sort(arr);
int begin=0;
int end=arr.length-1;
while (begin<end){
if (arr[begin]+arr[end]<sum)
begin++;
else if (arr[begin]+arr[end]>sum)
end--;
else{
System.out.println("两个数为:"+arr[begin]+" "+arr[end]);
begin++;
end--;
}
}
}
public static void main(String[] args) {
int array[]={1,9,5,4,6,3,7,2,8,11,10};
findSum1(array,10);
}