排序练习

1已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。

给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。

测试样例:
[2,1,4,3,6,5,8,7,10,9],10,2
返回:[1,2,3,4,5,6,7,8,9,10]

改进后的堆排序,取k个元素排序
import java.util.*;
 
public class ScaleSort {
    public int[] sortElement(int[] A, int n, int k) {
        if (A == null || A.length == 0 || n < k) {
            return A;
        }
        int[] heap = getKHeap(A, k);
        for(int i = k; i < n; i++){
            A[i - k] = heap[0];
            heap[0] = A[i];
            heapify(heap, 0, k);
        }
        for(int i = n - k; i < n; i++){
            A[i] = heap[0];
            swap(heap, 0, k - 1);
            heapify(heap, 0, --k);
        }
        return A;
         
    }
     
    public int[] getKHeap(int[] A, int k){
        int[] heap = new int[k];
        for(int i = 0; i < k; i++){
            heapInsert(heap, A[i], i);
        }
        return heap;
    }
     
     
    public void heapInsert(int[]A, int value, int index){
        A[index] = value;
        while(index != 0){
            int parent = (index - 1) / 2;
            if(A[parent] > A[index]){
                swap(A, parent, index);
                index = parent;
            }
            else{
                break;
            }
        }
    }
     
    public  void heapify(int[] arr, int index, int heapSize) {
        int left = index * 2 + 1;
        int right = index * 2 + 2;
        int smallest = index;
        while (left < heapSize) {
            if (arr[left] < arr[index]) {
                smallest = left;
            }
            if (right < heapSize && arr[right] < arr[smallest]) {
                smallest = right;
            }
            if (smallest != index) {
                swap(arr, smallest, index);
            } else {
                break;
            }
            index = smallest;
            left = index * 2 + 1;
            right = index * 2 + 2;
        }
    }
     
    public  void swap(int[] arr, int index1, int index2) {
        int tmp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = tmp;
    }
}

2请设计一个高效算法,判断数组中是否有重复值。必须保证额外空间复杂度为O(1)。

给定一个int数组A及它的大小n,请返回它是否有重复值。

测试样例:
[1,2,3,4,5,5,6],7
返回:true

堆排序,需要改写为非递归实现
import java.util.*;
  
public class Checker {
  
        public  boolean checkDuplicate(int[] a, int n) {
        if (a == null || n == 0) {
            return false;
        }
        heapSort(a);
        for (int i = 1; i < n; i++) {
            if (a[i] == a[i - 1]) {
                return true;
            }
        }
        return false;
    }
  
    public  void heapSort(int[] arr) {
        for (int i = 0; i != arr.length; i++) {
            heapInsert(arr, i);
        }
        for (int i = arr.length - 1; i != 0; i--) {
            swap(arr, 0, i);
            heapify(arr, 0, i);
        }
    }
  
    public  void heapInsert(int[] arr, int index) {
        while (index != 0) {
            int parent = (index - 1) / 2;
            if (arr[parent] < arr[index]) {
                swap(arr, parent, index);
                index = parent;
            } else {
                break;
            }
        }
    }
  
    public  void heapify(int[] arr, int index, int heapSize) {
        int left = index * 2 + 1;
        int right = index * 2 + 2;
        int largest = index;
        while (left < heapSize) {
            if (arr[left] > arr[index]) {
                largest = left;
            }
            if (right < heapSize && arr[right] > arr[largest]) {
                largest = right;
            }
            if (largest != index) {
                swap(arr, largest, index);
            } else {
                break;
            }
            index = largest;
            left = index * 2 + 1;
            right = index * 2 + 2;
        }
    }
  
    public  void swap(int[] arr, int index1, int index2) {
        int tmp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = tmp;
    }
      
      
      
}

3有两个从小到大排序以后的数组A和B,其中A的末端有足够的缓冲空容纳B。请编写一个方法,将B合并入A并排序。

给定两个有序int数组AB,A中的缓冲空用0填充,同时给定A和B的真实大小int n和int m,请返回合并后的数组。

import java.util.*;

public class Merge {
    public static int[] mergeAB(int[] A, int[] B, int n, int m) {
        int index=n+m-1;
        int i=n-1;
        int j=m-1;
        while(i>=0&&j>=0){
            if(A[i]>B[j]){
                A[index]=A[i];
                i--;
            }else{
                A[index]=B[j];
                j--;
            }
            index--;
        }
        while(j>=0){
            A[index]=B[j];
            j--;
            index--;
        }
        
        return A;
    }
}

加上

while(j>=0){
A[index]=B[j];
j--;
index--;
}

考虑到A中已合并完,而B中还有元素(若B合并完,A中还有元素,不用处理)

4有一个只由0,1,2三种元素构成的整数数组,请使用交换、原地排序而不是使用计数进行排序。

给定一个只含0,1,2的整数数组A及它的大小,请返回排序后的数组。保证数组大小小于等于500。

测试样例:
[0,1,1,0,2,2],6
返回:[0,0,1,1,2,2]
import java.util.*;
 
public class ThreeColor {
    public int[] sortThreeColor(int[] A, int n) {
        int p0 = 0;
        int p2 = n-1;
        int temp = 0;
        for (int i = 0 ;i < n ; i++){
            if ( p2 < i)
                break;
            if ( A[i] < 1){
                temp = A[i];
                A[i] = A[p0];
                A[p0] = temp;
                p0++;
            }
            if ( A[i] > 1){
                temp = A[i];
                A[i] = A[p2];
                A[p2] = temp;
                i--;
                p2--;
            }
        }
        return A;
    }
     
}

5现在有一个行和列都排好序的矩阵,请设计一个高效算法,快速查找矩阵中是否含有值x。

给定一个int矩阵mat,同时给定矩阵大小nxm及待查找的数x,请返回一个bool值,代表矩阵中是否存在x。所有矩阵中数字及x均为int范围内整数。保证nm均小于等于1000。

测试样例:
[[1,2,3],[4,5,6],[7,8,9]],3,3,10
返回:false
import java.util.*;

public class Finder {
   public boolean findX(int[][] mat,int n,int m,int x){
        int i=0;
        int j=m-1;
        while(i<n&&j>=0){
            if(mat[i][j]<x){
                i++;
            }else if(mat[i][j]==x){
                return true;
            }else if(mat[i][j]>x){
                j--;
            }
        }
        return false;
    }
}

牛客网上的答案

import java.util.*;
 
public class Finder {
    public boolean findX(int[][] mat, int n, int m, int x) {
        int a = n - 1 ;
        int b = 0 ;
        while ( a >= 0 && b < m ){
            if ( mat[a][b] == x )
                return true ;
            if ( mat[a][b] > x ){
                a-- ;
                if( a < 0 ){
                    break;
                }
            }
                 
            if ( mat[a][b] < x )
                b++ ;
        }
        return false;
    }
}

6

对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度。

给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度。(原序列位置从0开始标号,若原序列有序,返回0)。保证A中元素均为正整数。

测试样例:
[1,4,6,5,9,10],6
返回:2
import java.util.*;

public class Subsequence {
    public int shortestSubsequence(int[] A, int n) {
        // write code here
        int max=A[0];
        int min=A[n-1];
        int right=0;
        int left=0;
        for(int i=0;i<n;i++){
            if(A[i]>=max){
                max=A[i];
//                right=i;
            }else{
                right=i;
            }
        }
        for(int i=n-1;i>=0;i--){
            if(A[i]<=min){
                min=A[i];
//                left=i;
            }else{
                left=i;
            }
        }
        if(right==left){
            return 0;
        }else{
            return (right-left+1);
        }
    }
}

牛客网上的答案

import java.util.*;
 
public class Subsequence {
    public int shortestSubsequence(int[] A, int n) {
        // write code here
        int max = A[0],min = A[n-1],r = 0,l = 0;
        for (int i = 0;i < n;i++) {
            if (A[i] > max) max = A[i];
            else
                if (A[i] < max) r = i;
        }
        for (int j = n-1;j >= 0;j--) {
            if (A[j] < min) min = A[j];
            else
                if (A[j] > min) l = j;
        }
        if (r-l == 0) return 0;
        else return r-l+1;
    }
}

7有一个整形数组A,请设计一个复杂度为O(n)的算法,算出排序后相邻两数的最大差值。

给定一个int数组AA的大小n,请返回最大的差值。保证数组元素多于1个。

测试样例:
[1,2,5,4,6],5
返回:2
import java.util.*;

public class Gap {
    public int maxGap(int[] A, int n) {
        // write code here
        Arrays.sort(A);
        int max=A[1]-A[0];
        for(int i=2;i<n;i++){
            if(A[i]-A[i-1]>max)
                max=A[i]-A[i-1];
        }
        return max;
    }
}

牛客网上的答案:

利用桶排序的思想

import java.util.*;
 
public class Gap {
    public int maxGap(int[] A, int n) {
        // write code here
        if(null == A ||n<2) return 0;
        int min=Integer.MAX_VALUE;
        int max=Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            if(A[i]>max) max=A[i];
            if(A[i]<min) min=A[i];
        }
        if(min==max) return 0;
        boolean[] hasNum =new boolean[n+1];
        int[] maxs=new int[n+1];
        int[] mins=new int[n+1];
        for(int i=0;i<n;i++){
            int bid=bucket(A[i],n,min,max);
            maxs[bid]=hasNum[bid]?Math.max(maxs[bid],A[i]):A[i];
            mins[bid]=hasNum[bid]?Math.min(mins[bid],A[i]):A[i];
            hasNum[bid]=true;
        }
        int res=0;
        int lastMax=0;
        int i=0;
        while(i<=n){
            if(hasNum[i++]){
                lastMax = maxs[i-1];
                break;
            }
        }
        for(;i<=n;i++){
            if(hasNum[i]){
                res=Math.max(res,mins[i]-lastMax);
                lastMax=maxs[i];
            }
        }
        return res;
         
    }
    public int bucket(long num,long length,long min,long max){
        return (int)((num-min)*length/(max-min));
    }
}

 

posted @ 2017-04-24 15:58  临江仙zhe  阅读(119)  评论(0)    收藏  举报