[Prove safety Offer] 3 array duplicate numbers

Problem 1: array duplicate numbers

description

All numbers in an array of length n, where in 0 ~ (n-1) within the scope.
Some digital array is duplicated, but do not know how many numbers repeat, do not know each number was repeated several times.
Please find an array of arbitrary repeating digits.

  • Examples

    Input: an array of length {2,3,1,0,2,5,3} 7.
    Output: 2 or 3 duplicate numbers

Implementation code

class DuplicateNumber {

    /**
     * 暴力枚举 
     * 将数组中每个数与其他数对比 有重复就返回结果
     * 最差结果 n^2 最后两个重复
     */
    public static int bruteDuplicate(int[] arr, int length) {
        if (arr.length <= 0 || length <= 0) {
            return -1;
        }
        for (int i : arr) {
            if (i < 0 || i > length - 1) {
                return -1;
            }
        }

        for (int i = 0; i < length; i++) {
            for (int j = i+1; j < length; j++) {
                if (arr[i] == arr[j]) {
                    return arr[i];
                }
            }
        }

        return -1;
    }

    /**
     * 修改数组方法
     * 逐个排序,在排序过程中寻找重复数字
     * 从数组第一个数开始,将数字交换放入相应下标的位置,重复的数字必然会在交换过程中被发现
     * 最差结果为 n-1 数组内数字全部交换完
     * 
     * 有些类似桶方法,每个下标为一个桶,将元素放置到与下标相同的位置
     * 限制:连续的元素
     */
    public static int modifyArrayDuplicate(int[] arr, int length) {
        if (arr.length <= 0 || length <= 0) {
            return -1;
        }
        for (int i : arr) {
            if (i < 0 || i > length - 1) {
                return -1;
            }
        }

        for (int i = 0; i < length; i++) {
            // 将数组内数字和下标不相等的交换 直至发现数字重复
            while (arr[i] != i) {
                if (arr[i] == arr[arr[i]]) {
                    return arr[i];
                }

                // 交换
                int temp = arr[i];
                arr[i] = arr[temp];
                arr[temp] = temp;
            }
        }

        return -1;
    }
}
  • Test code
public class FindDuplicateNumber {

    public static void main(String[] args) {
        // 有多个重复数字
        unitTest(new int[]{2,3,1,0,2,5,3});
        // 有多个重复数字 偏后
        unitTest(new int[]{1,2,3,4,5,5,1});
        // 有一个重复数字 前后
        unitTest(new int[]{0,2,3,4,5,6,0});
        // 都是重复数字
        unitTest(new int[]{2,2,3,3});
        // 数组数字超出边界
        unitTest(new int[]{2,3,7,0,2,5,3});
        // 数组为空
        unitTest(new int[]{});
    }

    private static void unitTest(int[] array) {
        int length = array.length;
        printArray(array);
        System.out.println("暴力枚举" + DuplicateNumber.bruteDuplicate(array, length));
        System.out.println("桶排序" + DuplicateNumber.modifyArrayDuplicate(array, length));
    }

    private static void printArray(int[] arr) {
        System.out.print("array:\t" + arr.length + "\n");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println();
    }
}

Question 2: Do not modify the array to find duplicate numbers

description

In one of length n + 1 array where all numbers are 1 ~ n range.
Some digital array is duplicated, but do not know how many numbers repeat, do not know each number was repeated several times.
Please find an array of arbitrary repeating digits, but can not modify the input array.

  • Examples

    Input: {2,3,5,4,3,2,6,7} for the length of the array 8
    outputs: 2 or 3 duplicate numbers

  • note:

    This topic title do not contact with the
    subject but the conditions similar to but essentially different from the
    previous question is: There are n elements, there are n types of the same kind and number of elements may not be repeated occurrence of
    this problem is: There are n + 1 th element, there are n different species of number and types of elements would appear duplicate鸽舍原理

    Thinking

    Elements appear frequency by region, to identify duplicate numbers are displayed in this area

    鸽舍原理 n pigeons, (n-1) th loft, a loft must have two or more pigeons and

Zoning can be used二分法
3_2_ binary search must be repeated array of numbers

Implementation code

class DuplicateNumber {

   /**
     * 不修改数组方法 1~n
     * 鸽舍原理 + 二分查找 -- [1,3] 这4个数字在数组中出现5次,则必有一个数字出现两次及以上
     */
    public static int binarySearchDuplicate(int[] arr, int length) {
        if (arr.length <= 0 || length <= 0) {
            return -1;
        }
        for (int i : arr) {
            if (i < 0 || i > length - 1) {
                return -1;
            }
        }

        int start = 0;
        int end = length - 1;
        // 通过二分遍历元素种类 得到它在数组中出现的次数
        while (end >= start) {
            int middle = ((end - start) >> 1) + start;
            int count = countRange(arr, length, start, middle);
            
            if (end == start) {
                if (count > 1) {
                    return start;
                } else {
                    break;
                }
            }

            // 出现频次大于元素个数 则重复元素必然在此区间
            if (count > (middle - start + 1)) {
                end = middle;
            } else {
                start = middle + 1;
            }
        }

        return -1;
    }

    /**
     * 找出[start,end]在数组中出现的次数
     */
    private static int countRange(int[] arr, int length, int start, int end) {
        int count = 0;
        for (int i : arr) {
            if (i >= start && i <= end) {
                count++;
            }
        }
        return count;
    }
}
  • test
public class FindDuplicateNumber {

    public static void main(String[] args) {
        // 有多个重复数字
        unitTest(new int[]{2,3,1,4,2,5,3});
        // 有多个重复数字 偏后
        unitTest(new int[]{1,2,3,4,5,5,1});
        // 有一个重复数字 前后
        unitTest(new int[]{1,2,3,4,5,6,1});
        // 都是重复数字
        unitTest(new int[]{2,2,3,3});
        // 数组数字超出边界
        unitTest(new int[]{2,3,7,0,2,5,3});
        // 数组为空
        unitTest(new int[]{});
    }

    private static void unitTest(int[] array) {
        int length = array.length;
        printArray(array);
        System.out.println("二分查找" + DuplicateNumber.binarySearchDuplicate(array, length));
    }

    private static void printArray(int[] arr) {
        System.out.print("array:\t" + arr.length + "\n");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println();
    }
}

Guess you like

Origin www.cnblogs.com/slowbirdoflsh/p/11288475.html