[Algorithm]九章六之二: Array

来源:互联网 发布:c语言遗传算法原理 编辑:程序博客网 时间:2024/06/05 01:12

6. Merge Two Sorted Arrays :点击打开链接

class Solution {    /**     * @param A and B: sorted integer array A and B.     * @return: A new sorted integer array     */    public int[] mergeSortedArray(int[] A, int[] B) {        if(A==null || B==null){            return null;        }        int[] result=new int[A.length+B.length];        int i=0,j=0,index=0;                while(i<A.length && j<B.length){     //两个数组都从头元素一次比较,哪个的当前元素大,result数组里就装哪个            if(A[i]<B[j]){                result[index++]=A[i++];      //result数组的索引和两数组之一的索引同步推进            }else{                result[index++]=B[j++];            }        }        while(i<A.length){                   //当一个数组全部比较完,只剩下另一个数组的一些元素,也要全部转入result            result[index++]=A[i++];;        }        while(j<B.length){            result[index++]=B[j++];        }        return result;    }}

64. Merge Sorted Array:点击打开链接

因为添加或减少一个元素数组整体平移:O(n)

因此添加或减少m个元素而平移:O(m*n),与题O(m+n)不符,因此不能用整体平移

class Solution {    /**     * @param A: sorted integer array A which has m elements,      *           but size of A is m+n     * @param B: sorted integer array B which has n elements     * @return: void     */    public void mergeSortedArray(int[] A, int m, int[] B, int n) {  //这题要先理解题意,A有足够空间装所有A和B的元素        int i=m-1,j=n-1,lastIndex=m+n-1;                            //而且要merge B into A        while(i>=0 && j>=0){                                        //从后面开始,先放大的,倒着来            if(A[i]>B[j]){                                          //因为A和Bsorted array,所以不会存在没有地方放的情况                A[lastIndex--]=A[i--];                        }else{                A[lastIndex--]=B[j--];            }        }                while(i>=0){            A[lastIndex--]=A[i--];        }        while(j>=0){            A[lastIndex--]=B[j--];        }    }}

547.Intersection of Two Arrays:点击打开链接

public class Solution {    /**     * @param nums1 an integer array     * @param nums2 an integer array     * @return an integer array     */    public int[] intersection(int[] nums1, int[] nums2) {  //HashSet方法,time:O(n)        Set<Integer> set=new HashSet<>();        Set<Integer> intersect=new HashSet<>();                for(int i=0;i<nums1.length;i++){            if(!set.contains(nums1[i])){                set.add(nums1[i]);            }        }                for(int i=0;i<nums2.length;i++){            if(set.contains(nums2[i])){                intersect.add(nums2[i]);            }        }                int[] result=new int[intersect.size()];        int i=0;        for(Integer num:intersect){            result[i++]=num;        }        return result;    }}
public class Solution {    /**     * @param nums1 an integer array     * @param nums2 an integer array     * @return an integer array     */    public int[] intersection(int[] nums1, int[] nums2) {  //Sort arrays方法,time:O(nlogn)        Arrays.sort(nums1);                          //先sort        Arrays.sort(nums2);                Set<Integer> set=new HashSet<>();                int i=0,j=0;        while(i<nums1.length && j<nums2.length){                if(nums1[i]<nums2[j]){                  //哪个小哪个向前走一步                i++;            }else if(nums[i]>nums2[j]){                j++;            }else{                                  //两个相等的时候就加入到set,并且两个同时向前走一步                                set.add(nums1[i]);                    i++;                j++;            }        }                int[] result=new int[set.size()];        int index=0;        for(Integer num:set){            result[index++]=num;        }        return result;    }}
public class Solution {    /**     * @param nums1 an integer array     * @param nums2 an integer array     * @return an integer array     */    public int[] intersection(int[] nums1, int[] nums2) {  //binarySearch方法,time:O(nlogn)     if (nums1 == null || nums2 == null) {            return null;        }                Set<Integer> set = new HashSet<>();                Arrays.sort(nums1);        for (int i = 0; i < nums2.length; i++) {            if (binarySearch(nums1, nums2[i])) {                set.add(nums2[i]);            }        }                int[] result = new int[set.size()];        int index = 0;        for (Integer num : set) {            result[index++] = num;        }        return result;    }        private boolean binarySearch(int[] nums,int target){        if(nums==null || nums.length==0){            return false;        }        int start=0, end=nums.length-1;        while (start + 1 < end) {            int mid=(end-start)/2+start;            if(nums[mid]==target) {                return true;            }            if(nums[mid]<target) {                start = mid;            }else {                end = mid;            }        }                if(nums[start]==target) {            return true;        }        if(nums[end]==target) {            return true;        }        return false;    }}

548.Intersection of Two ArraysII :  点击打开链接

public class Solution {    /**     * @param nums1 an integer array     * @param nums2 an integer array     * @return an integer array     */    public int[] intersection(int[] nums1, int[] nums2) {  //输出所有的重复元素        if(nums1==null || nums2==null){            return null;        }                Arrays.sort(nums1);        Arrays.sort(nums2);                List<Integer> temp=new ArrayList<>();             //换成一个list乘装暂时的重复元素,再向数组里倒        int i=0,j=0;        while(i<nums1.length && j<nums2.length){            if(nums1[i]<nums2[j]){                i++;            }else if(nums1[i]>nums2[j]){                j++;            }else{                temp.add(nums1[i]);                i++;                j++;            }        }                int[] result=new int[list.size()];        int index=0;        for(Integer num:list){            result[index++]=num;        }        return result;    }}

65.Median of Two Sorted Arrays:点击打开链接

1. 如果数组A和B的总长度length是奇数,中位数就是第length / 2 + 1小的数,

    如果length是偶数,中位数就是第length / 2小的数和length / 2 + 1小的数的平均数。

2. 要在两个排序的数组A和B(记成新数组)中找第k小的数,

    我们希望用O(1)的时间把问题分解成:在数组A和数组B中分别找第k / 2小的数。

3. 我们比较数组A中第k / 2小的数和数组B中第k / 2小的数:

    如果A[k / 2 - 1] < B[k / 2 - 1],说明在新数组中第k小的数不可能是A[k/2 - 1]以及这个数之前的数字, 

    那么我们可以把这k / 2个数字从A数组中踢掉,并在B数组和 过数的A数组里    分别找第k / 2小的数

    同理,如果B[k / 2 - 1] < A[k / 2 - 1],我们可以把k / 2个数字从B数组中踢掉,并在A数组和踢过数的B数组里分别找第k / 2小的数。

class Solution {    /**     * @param A: An integer array.     * @param B: An integer array.     * @return: a double whose format is *.5 or *.0     */    public double findMedianSortedArrays(int[] A, int[] B) {        int length=A.length+B.length;        if(length%2==0){            return (findKth(A,0,B,0,length/2)+findKth(A,0,B,0,length/2+1))/2.0;        }        return findKth(A,0,B,0,length/2+1);    }    private int findKth(int[] A,int startA,int[] B,int startB,int k){        if(startA>=A.length){                                                //如果A变成null,就成了B数组单独找Kth            return B[startB+k-1];        }        if(startB>=B.length){                                                //如果B变成null,就成了A数组单独找Kth            return A[startA+k-1];        }        if(k==1){                                                            //如果找第一大的数,就是A,B数组中的第一个小值            return Math.min(A[startA],B[startB]);        }                int valueA=startA+k/2-1<A.length?A[startA+k/2-1]:Integer.MAX_VALUE;  //哪个数组不够了,就用无穷大后面补全        int valueB=startB+k/2-1<B.length?B[startB+k/2-1]:Integer.MAX_VALUE;        if(valueA<valueB){                                                               return findKth(A,startA+k/2,B,startB,k-k/2);        }        return findKth(A,startA,B,startB+k/2,k-k/2);    }}

41. Mixmam Subarray:点击打开链接

PrefixSum[i]=nums[0]+nums[1]+...+nums[i-1],PrefixSum[0]=0;

例如:int [ ] num={1,2,3,4,-5}

PrefixSum[0]=0,

PrefixSum[1]=nums[0]=1;

PrefixSum[2]=nums[0]+nums[1]=1+2=3;

PrefixSum[3]=nums[0]+nums[1]+nums[2]=1+2+3=6;

PrefixSum[4]=nums[0]+nums[1]+nums[2]+nums[3]=1+2+3+4=10;

PrefixSum[5]=nums[0]+nums[1]+nums[2]+nums[3]+nums[4]=1+2+3+4+(-5)=5;

public class Solution {    /**     * @param nums: A list of integers     * @return: A integer indicate the sum of max subarray     */    public int maxSubArray(int[] nums) {        if(nums==null || nums.length==0){            return 0;        }                int sum=0;        int maxVal=Integer.MIN_VALUE;        int minSum=0;        for(int i=0;i<nums.length;i++){            sum+=nums[i];            maxVal=Math.max(maxVal,sum-minSum);    //每次拿到一个当前最大值,都要比较(当前最大值)与(当前sum-当前最小和)的小大            minSum=Math.min(minSum,sum);           //如果当前sum-当前最小和,自然得到就是当前最大值        }        return maxVal;    }}

42. Maximum SubArray II: 点击打开链接

public class Solution {    /**     * @param nums: A list of integers     * @return: An integer denotes the sum of max two non-overlapping subarrays     */    public int maxTwoSubArrays(ArrayList<Integer> nums) {        int maxVal=Integer.MIN_VALUE;        int minSum=0;        int sum=0;        int[] left=new int[nums.size()];        for(int i=0;i<nums.size();i++){                   //左边开始相加,left[i]表示到i当前的最大值            sum+=nums.get(i);            maxVal=Math.max(maxVal,sum-minSum);            minSum=Math.min(sum,minSum);            left[i]=maxVal;        }                maxVal=Integer.MIN_VALUE;        minSum=0;        sum=0;        int[] right=new int[nums.size()];        for(int i=nums.size()-1;i>=0;i--){                //右边开始相加,right[i]表示到i当前的最大值            sum+=nums.get(i);            maxVal=Math.max(maxVal,sum-minSum);            minSum=Math.min(sum,minSum);            right[i]=maxVal;        }                maxVal=Integer.MIN_VALUE;        for(int i=0;i<nums.size()-1;i++){            maxVal=Math.max(maxVal,left[i]+right[i+1]);  //最后对每一个左边最大,与比它向后一个位置的右边最大的和取最大        }        return maxVal;    }}

138.Subarray Sum:点击打开链接

思路:子数组和为一个数,无非就是两种情况,从头开始的subarray,和从中间某一个位置开始的subarray

         对于从中间某一位置i开始的subarray,例如前i位置之和为3,而从i+1 ~ j这一段加起来还是3,说明i+1 ~ j这段和为0

注意:如果需要计算子数组从下标i到下标j之间的所有数之和,则有:Sum(i~j)=PrefixSum[j+1]-PrefixSum[i]

public class Solution {    /**     * @param nums: A list of integers     * @return: A list of integers includes the index of the first number      *          and the index of the last number     */    public ArrayList<Integer> subarraySum(int[] nums) {                          //方法一        ArrayList<Integer> result=new ArrayList<>();        if(nums==null || nums.length==0){            return result;        }                Map<Integer,Integer> map=new HashMap<>();        int sum=0;        for(int i=0;i<nums.length;i++){            sum+=nums[i];            if(!map.containsKey(sum)){                 //从头开始的每一个preSum                map.put(sum,i);                if(sum==0){                   result.add(0);                    result.add(i);                   break;                }               }else{                                     //非从头开始(中间段)的每一个preSum                result.add(map.get(sum)+1);                result.add(i);                break;            }        }        return result;    }}

public class Solution {    /**     * @param nums: A list of integers     * @return: A list of integers includes the index of the first number      *          and the index of the last number     */    public ArrayList<Integer> subarraySum(int[] nums) {                          //方法二:同样思路        ArrayList<Integer> ans = new ArrayList<Integer>();        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();        map.put(0, -1);                                   //先放入sum为0,位置为-1              int sum = 0;        for (int i = 0; i <nums.length; i++) {            sum += nums[i];            if (map.containsKey(sum)) {                   //有同样的sum出现,就取之前出现sum的前一个位置和当前sum位置                      ans.add(map.get(sum) + 1);                ans.add(i);                return ans;            }            map.put(sum, i);                              //只要有新的sum就放入到sum和位置i,表示从0开始到i的这段sum        }        return ans;    }}

560. Subarray Sum Equals K:点击打开链接

public class Solution {    public int subarraySum(int[] nums, int k) {                       if(nums==null || nums.length==0){            return 0;        }                Map<Integer,Integer> map=new HashMap<>();        int result=0;        int sum=0;                map.put(0,1);                                     //考虑到从头开始的情况,要先放入sum为0,次数为1,不然会空指针异常        for(int i=0;i<nums.length;i++){              sum+=nums[i];            if(map.containsKey(sum-k)){                   //每到一个数                result+=map.get(sum-k);            }            map.put(sum,map.getOrDefault(sum,0)+1);       //用map来保存当前数组从头开始的前i项和的次数        }        return result;    }}

public class Solution {    public int subarraySum(int[] nums, int k) {           //brute force方法        if(nums==null || nums.length==0){            return 0;        }                int count=0;        for(int i=0;i<nums.length;i++){            int sum=0;            sum+=nums[i];            if(sum==k){                count++;            }            for(int j=i+1;j<nums.length;j++){                sum+=nums[j];                if(sum==k){                    count++;                }            }        }        return count;    }}

139.Subarray Sum Closet: 点击打开链接

思路:如果需要计算子数组从下标i到下标j之间的所有数之和,则有:Sum(i~j)=PrefixSum[j+1]-PrefixSum[i]
         本题只要不断更新使Sum(i~j)尽可能接近0
class Pair {    int sum;    int index;    public Pair(int sum, int index) {        this.sum = sum;        this.index = index;    }}    public class Solution {    /**     * @param nums: A list of integers     * @return: A list of integers includes the index of the first number      *          and the index of the last number     */    public int[] subarraySumClosest(int[] nums) {        int[] result=new int[2];        if(nums==null || nums.length==0){            return result;        }                int len=nums.length;        if(len==1){            result[0]=result[1]=0;        }                Pair[] preSum=new Pair[len+1];                       //preSum表示的是前i个元素和,和对应的索引i-1        int pre=0;                                           //也就是preSum[3],前3个元素和,是0,1,2,因此索引是2        preSum[0]=new Pair(0,0);        for(int i=1;i<=len;i++){                             //for循环拿到前i个元素和            preSum[i]=new Pair(pre+nums[i-1],i);            pre=preSum[i].sum;        }                Arrays.sort(preSum,new Comparator<Pair>(){           //然后重新排序preSum,按照和的大小            public int compare(Pair p1,Pair p2){             //因此重新排序后preSum表示的在数组preSum中第几大                return p1.sum-p2.sum;                                   }        });                int closet=Integer.MAX_VALUE;        for(int i=1;i<=len;i++){            if(preSum[i].sum-preSum[i-1].sum<closet){        //两两一次遍历记录当前最小的差,也就是对应的索引差最接近0                closet=preSum[i].sum-preSum[i-1].sum;                int[] temp=new int[]{preSum[i-1].index-1,preSum[i].index-1};                Arrays.sort(temp);                result[0]=temp[0]+1;                result[1]=temp[1];            }        }        return result;    }}