数据结构与算法练习-排序

来源:互联网 发布:为知笔记 archlinux 编辑:程序博客网 时间:2024/05/19 13:43

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

描述

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

分析

  • 这里很容易联想到快速排序基于中间值,左右两边基本有序的方法。但是快速排序是一个不稳定算法,会改变数与数之间的位置,虽然能满足题干的前半部分,但是满足不了条件—并保证奇数和奇数,偶数和偶数之间的相对位置不变。
  • 考虑其他的排序方法中,维持一个队列有序的稳定排序方法—插入排序

代码

//这是一个错误的解决方式,使用快速排序public static void reOrderArrayError(int[] array) {        if (array == null || array.length == 0 || array.length == 1) {            return;        }        int temp = array[0];        int i = 0, j = array.length - 1;        while (i < j) {            while (i < j && array[i] % 2 == 1) {                i++;            }            if (i < j) {                array[j] = array[i];            }            while (i < j && array[j] % 2 == 0) {                j--;            }            if (i < j) {                array[i] = array[j];            }        }        array[i] = temp;    }//插入排序    public static void reOrderArray(int[] array) {        if (array == null || array.length == 0 || array.length == 1) {            return;        }        for (int i = 0; i < array.length; i++) {            if (array[i] % 2 == 1) {                int j = i - 1;                int temp = array[i];                while (j >= 0 && array[j] % 2 == 0) {                    array[j + 1] = array[j];                    j--;                }                array[j+1] = temp;            }        }

测试

public void testReOrderArray() {        int[] array = { 1, 2, 3, 4, 5, 6, 7 };        int[] curArray = { 1, 3, 5, 7, 2, 4, 6 };        Number.reOrderArray(array);        for (int i = 0; i < array.length; i++) {            assertEquals(array[i], curArray[i]);            // Log.d("TAG", array[i]+" ");        }    }

寻找最小的K个数

描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

分析

冒泡排序或者插入排序找出数组中最大的4个数即可。时间复杂度不用N*N 时间复杂度N*K(K<=N)

代码

public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {        ArrayList<Integer> list = new ArrayList<Integer>();        if (input == null || input.length < k || k <= 0) {            return list;        }        for (int i = 0; i < k; i++) {            for (int j = 0; j < input.length - i - 1; j++) {                if (input[j] < input[j + 1]) {                    int temp = input[j];                    input[j] = input[j + 1];                    input[j + 1] = temp;                }            }            list.add(input[input.length - i - 1]);        }        return list;    }

测试

private NumberSolution solution;    private int[] array = { 1, 6, 5, 6, 1, 2, 3, 4 };    private ArrayList<Integer> aMin2;    private ArrayList<Integer> aMin3;    private ArrayList<Integer> aMin4;    @Override    protected void setUp() throws Exception {        solution = new NumberSolution();        super.setUp();        aMin2 = new ArrayList<Integer>();        aMin2.add(1);        aMin2.add(1);        aMin3 = new ArrayList<Integer>(aMin2);        aMin3.add(2);        aMin4 = new ArrayList<Integer>(aMin3);        aMin4.add(3);    }    public void testGetLeastNumbers_Solution() {        assertEquals(aMin2, solution.GetLeastNumbers_Solution(array, 2));        assertEquals(aMin3, solution.GetLeastNumbers_Solution(array, 3));        assertEquals(aMin4, solution.GetLeastNumbers_Solution(array, 4));    }

数组里所有数字拼接起来排成一个最小数

描述

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

分析

其实就是把数组按照特定规则排序。{3,32,321}—>{321,32,3}
仔细观察这很像是按照字符串自然顺序比较,比较规则
String a,b

如果ab>ba说明a>b
如果ab=ba说明a=b
如果ba>ab表示b>a

代码

public String PrintMinNumber(int[] numbers) {        if (numbers == null || numbers.length == 0) {            return "";        }        int length = numbers.length;        String[] numStrs = new String[length];        for (int i = 0; i < length; i++) {            numStrs[i] = numbers[i] + "";        }        Arrays.sort(numStrs, new Comparator<String>() {            @Override            public int compare(String s1, String s2) {                String total1 = s1 + s2;                String total2 = s2 + s1;                return total1.compareTo(total2);            }        });        StringBuilder sb = new StringBuilder();        for (int i = 0; i < length; i++) {            sb.append(numStrs[i]);        }        return sb.toString();    }

测试

    private int[] array = { 3, 32, 321 };    private String result = "321323";    @Override    protected void setUp() throws Exception {        solution = new NumberSolution();        super.setUp();    }    public void testPrintMinNumber() {        assertEquals(result, solution.PrintMinNumber(array));    }

统计一个数字在排序数组中出现的次数

分析

二分法递归查找k第一次出现的位置n,然后再二分查找k第二次出现的位置m,m-n+1就是k的个数。时间复杂度log(N)+log(N)

代码

    public int getFirst(int[] array, int s, int e, int k) {        if (s >= e) {            return array[e] == k ? e : -1;        }        int mid = (s + e) / 2;        if (array[mid] < k) {            return getFirst(array, mid + 1, e, k);        } else {            return getFirst(array, s, mid, k);        }    }    public int getEnd(int[] array, int s, int e, int k) {        if (s >= e) {            return array[s] == k ? s : -1;        }        int mid = (s + e) / 2;        if (array[mid] <= k) {            return getEnd(array, mid, e, k);        } else {            return getEnd(array, s, mid - 1, k);        }    }    public int GetNumberOfK(int[] array, int k) {        if (array == null || array.length == 0) {            return 0;        }        if (array[0] > k || array[array.length - 1] < k) {            return 0;        }        int first = getFirst(array, 0, array.length - 1, k);        int end = getEnd(array, 0, array.length - 1, k);        return end - first + 1;    }

测试

    public void testGetNumberOfK() {        int[] array = { 1, 2, 3, 3, 3, 3, 4, 5 };        assertEquals(2, solution.getFirst(array, 0, array.length - 1, 3));        int end = solution.getEnd(array, 0, array.length - 1, 3);        assertEquals(5, end);        assertEquals(4, solution.GetNumberOfK(array, 3));    }
1 0
原创粉丝点击