[剑指offer]大可日常打卡-数组

4.二维数组中的查找

题目描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

思路:从右上角的数开始比,要是等于就返回true;小于target就row++;大于target就col--,所以列的--应该在最外层循环,满足当前列所对应的那个条件,row++。

public class Solution {
    public boolean Find(int target, int [][] array) {
        if(array==null||array.length==0||array[0].length==0||array[0][0]>target){
            return false;
        }
        int row=array.length;
        int col=array[0].length;
        for(int j=col-1;j>=0;j--){
            
            for(int i=0;i<row;i++){
                if(array[i][j]==target){
                    return true;
                }else if(array[i][j]>target){
                    break;
                }else{//array[i][j]<target
                    continue;
                }
            }
        }
        return false;
    }
}

11.旋转数组的最小数字

题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

思路:首先采用一个笨办法,就是找出数组里的最小值,就遍历找最小值,但是这个肯定不是最好的方法,因为这样就没有用到数组是非减排序的数组的一个旋转这个条件!!

新思路:根据题意所得,数组可以分为两个部分,为两个递增排序的子数组,且第一个数组的数都大于第二个数组的数,但是有一个特殊情况稍后说。三个指针指向的数都相等的时候,那么就顺序查找。

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array==null||array.length==0){
            return 0;
        }
        int left=0;
        int right=array.length-1;
        int mid=left;
        while(left<right){
            if(right-left==1){
                return array[right];
            }
            mid=(right+left)/2;
            if(array[left]==array[right]&&array[right]==array[mid]){
                //顺序查找
                return findMin(array);
            }
            //判断Mid位置的数字在前一个递增数组中还是后一个递增数组中
            if(array[mid]<array[left]){
                //在第二个里面,中间的数小于左边指针指的数
                right=mid;
                continue;
            }else if(array[mid]>array[right]){
                //说明在第一个数组里面
                left=mid;
                continue;
            }
        }
        
        return array[right];
    }
    public static int findMin(int[] array){
        int min=array[0];
        for(int i=0;i<array.length;i++){
            if(array[i]<min){
                min=array[i];
            }
        }
        return min;
    }
}

21.调整数组顺序使奇数位于偶数前面

题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

思路:一开始想的是用两个指针,一个指向数组开头,然后如果是奇数,就往后移一个位置,如果是偶数,那么就和偶数的指针交换,利用快排思想来实现,但是行不通,因为题目要求保证奇数和奇数,偶数和偶数之间的相对位置不变,即需要是稳定的,那么就需要多申请空间了。两个队列一个放奇数,一个放偶数。

import java.util.Queue;
import java.util.LinkedList;
public class Solution {
    public void reOrderArray(int [] array) {
        if(array==null||array.length==0){
            return;
        }
        Queue<Integer> odd=new LinkedList<>();
        Queue<Integer> even=new LinkedList<>();
        for(int i=0;i<array.length;i++){
            if(array[i]%2==0){
                even.add(array[i]);
            }else{
                odd.add(array[i]);
            }
        }
        int i=0;
        while(!odd.isEmpty()){
            array[i]=odd.remove();
            i++;
        }
        while(!even.isEmpty()){
            array[i]=even.remove();
            i++;
        }
        
    }
}

39.数组中出现次数超过一半的数字

题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路:一个数字出现次数超过数组长度的一半意味着,把数组进行排序,如果有出现次数超过数组长度一半的数,中位数肯定是我们所求的数字。下面我们就是要看它出现次数是不是超过数组长度的一半,即计算它出现次数,可以参考快排思路。如果超过数组长度一半,那么就返回该数,否则说明不存在,返回0。

import java.util.Arrays;
public class Solution {
    public static int MoreThanHalfNum_Solution(int[] array) {
        if(array==null||array.length<1){
            return 0;
        }
        Arrays.sort(array);
        
        int mid=array.length/2;
        //计算出现次数
        int left=mid-1;
        int right=mid+1;
        
        int times=1;
        while(left>=0){
            if(array[left]==array[mid]){
                times++;
                
                left--;
                continue;
            }else{
            	break;
            }
            
            
        }
        while(right<array.length){
            if(array[right]==array[mid]){
                times++;
                right++;
                continue;
            }else{
            	break;
            }
        }
        
        if(times>array.length/2){
            return array[mid];
        }
        return 0;
    }
}

42.连续子数组的最大和

题目描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

思路:从数组第一个开始加,如果两个数加起来的结果小于当前max,那么max不变

 

牛客剑指offer:

1.数组中重复的数字

题目描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

思路:hashmap,挨个遍历,没出现过就存进去,出现过就是它!

import java.util.HashMap;
public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int[] duplication) {
        if(numbers==null||numbers.length==0){
            return false;
        }
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<numbers.length;i++){
            if(map.containsKey(numbers[i])){
                duplication[0]=numbers[i];
                return true;
                
            }else{
                map.put(numbers[i],1);
            }
        }
        return false;
        
    
    }
}

42.连续子数组的最大和

题目描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)。

思路:维护一个累加的和和最大和,如果和小于0的话,那么再往上加后面的不管什么,数都只会更小不会更大,所以如果当前和小于0的话,那么就把当前值设为最大值,否则就往上加。

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        if(array==null||array.length<0){
            return 0;
        }
        int max=array[0];
        int current=array[0];
        for(int i=1;i<array.length;i++){
            //挨个遍历
            //current+=array[i];
            if(current<0){
                current=array[i];
            }else{
                current+=array[i];
            }
            
            if(current>max){
                max=current;
            }
        }
        return max;
        
    }
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值